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?
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").
Hallo, hm ja das wäre die eleganteste Methode. Nur blöd, das ich noch nie was mit einem 2. Thread gemacht habe. Soll ja angeblich ned so einfach sein, auf globale Variablen und so zuzugreifen...
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 :-)
Christian schrieb: > Nach dem Sensen muss kurz gewartet werden, bis die Daten kommen. > Da muss das Programm kurz warten. warum soll denn da gewartet werden? Man empfängt sofort denach die Daten und legt einen Tiemout fest bis wann die Daten eintreffen müssen.
Hallo, gut, dann muss ich das mit den Variablen wohl dementsprechend machen. Aber mit den Labels habe ich halt noch die Probleme. ich hab mir das mit dem Invoke schon mal angeschaut, aber ich verstehts leider ned...
@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...
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 | } |
Hallo, könnte mir da jemand ein Beispiel zeigen, wie das jetzt konkret bei einem Label ausschauen würde?
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!
Peter II schrieb: > 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. Ich denke sein Problem ist, dass der Aufruf zum Empfangen der Daten synchron abläuft und daher den GUI Thread lahmlegt.
Ich denke das er kein Protokoll hat ! Im einfachsten Fall warten bis ein Return kommt für den Zeilenrücklauf. Falls es nicht innerhalb einer bestimmten Zeit kommt (z.B 10 Sekunden) ... Timeout. Danach die Daten die Vor dem return sthen verarbeiten.
Muß dann natürlich blockierend sein und in einem extra Thread laufen, wenn er das GUI nicht blockieren will.
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); |
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.
Christian schrieb: > Soll ja angeblich ned so einfach sein, auf globale Variablen und so > zuzugreifen... C++, also objektorientierte Programmierung, und "globale Variablen" beißen sich, aber extrem...
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.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.