C++/CLI Programmpause

Gast #3128868
Lesenswert?

Hallo,
mein Programm kommuniziert über die RS232 Schnittstelle mit einem Gerät.
Zuerst wird ein Befehl gesendet, um Daten anzufordern, dann sendet
das Derät Daten.
Nach dem Sensen muss kurz gewartet werden, bis die Daten kommen.
Da muss das Programm kurz warten.

Mit Tread->Sleep friert mir leider die ganze Oberfläche ein..
Wenn ichs mit Timern mache führt das jetzt ins Chaos, weil dann
Timer den anderen wieder stoppen muss usw.
Gibts irgendeine elegante Variante, die wartet, aber mir nicht das 
Programm einfriert?
#3128871
Lesenswert?

Christian schrieb:
> Mit Tread->Sleep friert mir leider die ganze Oberfläche ein

Du bist lustig. Machst du etwa alles aus einem Thread heraus? Das kann 
nur Ärger geben ;-)

Der richtige Ansatz wäre: Dein Haupt-Thread (GUI) started einen 
Hintergrund-Thread, in welchem die ganze RS232 Geschichte abläuft. Der 
Thread kann dann Sleepen so viel er will, dein Programm bleibt trotzdem 
"responsive". Stichwort "Backgroundworker".

Wenn du dann die GUI updaten willst, kann der Hintergrundthread einfach 
dort hineinrufen, und z.B. Ausgaben anzeigen lassen (Stichwort 
"Invoke").
#3128877
Lesenswert?

Naja, der Zugriff auf globale Variablen ist im Prinzip schon einfach. 
Schwierig wird's nur, wenn sich beide Threads dann ins Gehege kommen. 
Daher sollte man das vermeiden.

Deswegen würde ich dir raten, deine Architektur so aufzubauen, dass 
beide Threads möglichst unabhängig sind. Globale Variablen gehören 
sowiso nicht zum guten Ton ;-) Ich würde wetten, dass auch ohne 
auskommst. Dann klappt's auch mit dem 2ten Thread...

Falls du konkrete Architektur- bzw. Thread-Fragen hast, wird dir hier 
sicherlich gerne weitergeholfen :-)
#3128895
Lesenswert?

Christian schrieb:
> ich hab mir das mit dem Invoke schon mal angeschaut, aber ich verstehts
> leider ned...

Eigentlich garnicht so schwer:
Dein 2ter Thread darf nicht einfach so auf die GUI zugreifen. Das darf 
nur der GUI Thread. Wenn Thread 2 also z.B. sowas machen möchte: 
"mLabel1.Text = CoolDataThatWasJustReceived.ToString()" fliegt eine 
Exception.

Deswegen benutzt man den Invoke. Damit kann man sagen, dass ein Stück 
Code auf dem GUI Thread ausgeführt werden soll. Dann gibt's keine 
Probleme.

So sieht das z.B. in C# aus (sehr generisches Beispiel, in deinem Fall 
ist das einfacher):
1
public static void SetControlPropertyThreadSafe(Control control, string propertyName, object propertyValue)
2
{
3
  if (control.InvokeRequired)
4
  {
5
    control.Invoke(new SetControlPropertyThreadSafeDelegate(SetControlPropertyThreadSafe), new object[] { control, propertyName, propertyValue });
6
  }
7
  else
8
  {
9
    control.GetType().InvokeMember(propertyName, BindingFlags.SetProperty, null, control, new object[] { propertyValue });
10
  }
11
}
Gast #3129029
Lesenswert?

Christian schrieb:
> @Peter II
> Bis das Gerät eine Antwort schickt dauerts ein bisschen. Und wenn das
> ganze dann auch noch übers Netzwerk läuft und das ausgelastet ist,
> dauerts schon mal 200 ms bis die Antwort kommt.
> Wenn ich dann auslese bevor die Antwort kommt bekomme nichts...

klar bekommst du nichst. Wo ist das Problem? Wenn du den Timeout auf 10 
Sekunden festlegst, dann ist es egal ob die ersten 200ms nichts kommt.

Wenn du aber fest wartest und die daten kommen mal schneller, dann gehen 
sie im zweifelfall sogar verloren!
Gast #3131156
Lesenswert?

Hallo,
ich sende ein Byte und nach dem senden des Bytes muss ich mindestens 
50ms warten, bevor ich den read befehl gebe.
Ansonsten erhalte ich keinen Wert.
Warum und wieso, keine Ahnung.
Timesout habe ich schon.
1
comPort1 = Convert::ToString(totdelport);serialPort1 = gcnew SerialPort(comPort1,9600,Parity::None,8,StopBits::One);
2
serialPort1->ReadTimeout = 1500;
3
serialPort1->Open();
4
  
5
Byte1 = 0x73;
6
Senden[0] = Byte1;
7
serialPort1->Write(Senden,0,1);
8

9
Thread::Sleep(50);
10

11
serialPort1->Read(Empfangen,0,8);
Gast #3131166
Lesenswert?

Christian schrieb:
> ich sende ein Byte und nach dem senden des Bytes muss ich mindestens
> 50ms warten, bevor ich den read befehl gebe.
> Ansonsten erhalte ich keinen Wert.

das ist ziemlich unlogisch. Denn intern macht der computer immer einen 
Read. Nur das es es in einen Puffer einliest. Das würde ich erstmal 
untersuchen in dem du nicht gleich ein read mit 8 zeichen danach machst 
sondern mal einzelen Zeichen einließt. Nicht das noch etwas anderes 
kommt als du erwartest.
Gast #3134087
Lesenswert?

Christian schrieb:
> könnte mir da jemand ein Beispiel zeigen, wie das jetzt konkret bei
> einem Label ausschauen würde?

Nach der Methode von Boris B einfach aus dem Thread heraus:
SetControlPropertyThreadSafe(NameDesLabelsZBLabel1,"Text","Hallo");
...das entspricht quasi
NameDesLabelsZBLabel1.Text="Hallo";
nur das sichergestellt wird, dass diese Zeile im gleichem Thread 
aufgerufen wird, indem auch NameDesLabelsZBLabel1 erzeugt wurde (sofern 
das Control sagt dass das nötig ist)

Andere Möglichkeiten kann man auch hier finden:
http://stackoverflow.com/questions/2367718/automating-the-invokerequired-code-pattern

Beim BackgroundWorker (eine Art Wrapper-Klasse um einen Thread) kann man 
.ReportProgress() nutzen um Daten an den GUI-Thread zu übermitteln.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren