Autor |
Beitrag |
Abayo
Hält's aus hier
Beiträge: 4
|
Verfasst: Di 20.08.13 16:56
Hi @ all!
Ich möchte ein kleines Programm zur kommunikation mit einem Beagleboard schreiben und bräuchte ein wenig hilfe dabei wie ich am besten anfange.
Folgendes möchte ich mit C# auf meinem Rechner machen:
Eine GUI erstellen mithilfe von WPF bei der ich in Textfelder gewünschte Werte eingeben kann und diese dann an das BB schicken über einen RS232-USB konverter.
Das Board sendet dann antworten nach berechnung zurück.
Wie ich zwischen dem FTDI-Device und der Benutzeroberfläche kommuniziere habe ich schon herausbekommen. Allerdings wird meine Benutzeroberfläche dabei blockiert (wenn ich z.B. auf antworten warte), weshalb ich mir dachte das ich dafür einen zweiten Thread verwende.
Nun stellt sich mir aber folgende Frage (bin noch nicht sehr erfahren mit multithreading in C#):
Wie kann ich zwischen meiner GUI und dem thread kommunizieren?
Ich hatte mir überlegt den "kommunikationsthread" ständig laufen lassen und wenn dieser eine Antwort bekommt, dann soll er die Daten an die GUI senden.
Für Threads gibt es ja die möglichkeit einen eigenen thread zu erstellen und diesem eine methode zu übergeben oder aber einen backgroundworker für eine methode zu machen (was ich so gelesen habe erscheinen mir diese beiden für mich am sinnvollsten).
Wie bekomme ich aber nun die empfangenen Daten an die GUI, ohne den Thread zu beenden? -> ich glaub ich kann eine eigene klasse machen und die klassen methode an den thread übergeben. diese sollte dann doch in der lage sein auf die klassenparameter zuzgreifen nachdem der thread beendet ist, oder? (bin mir noch nicht sicher ob das so geht, habe noch nichts darüber gefunden)
Oder ist es gar nicht sinnvoll den Kommunikationsthread dauernd laufen zu lassen? (wollte den auf ständig "lesen" stellen und nur bei Bedarf auf "senden")
Wäre es sinnvoller mit einem Timer alle paar ms (ca alle 15 ~ 40 ms) eine Lesemethode mit dem Background worker zu starten und das eingelesene in eine globale Variable zu speichern?
Hoffe ihr könnt nachvollziehen was ich meine!
mfg,
|
|
IhopeonlyReader
      
Beiträge: 600
Erhaltene Danke: 23
Delphi 7 PE
|
Verfasst: Di 20.08.13 17:47
Wozu brauchst du sie in der Gui?
Wenn sie in der Gui wirklich benötigt werden, musst du warten bis der Thread fertig ist und dann über eine property auf ds "fertige" zugreifen..
(falls nicht fertig ist property leer sonst steht das fertige drin)
Wenn du sie nur anzeigen willst musst du eine synchronizierte procedure im "kommunikationsthread" aufrufen, das Labels etc. über den hautthread aktualisiert..
Ich sehe selbst keinen Sinn darin etwas in Thread C zu berechnen und in Thread A darauf zu warten... und ich denke auch nicht dass die Daten in der GUI-Thread benötigt werden, sondern in der GUI selbst.. und das erreichst du am besten im Thread C (oder bei dir kommunikationsthread) am ehesten 
_________________ Sucht "neueres" Delphi
Wer nicht brauch was er hat, brauch auch nicht was er nicht hat!
|
|
Th69
      

Beiträge: 4796
Erhaltene Danke: 1059
Win10
C#, C++ (VS 2017/19/22)
|
Verfasst: Di 20.08.13 18:57
Hallo Abayo
m.E. scheint der Backgroundworker für dein Vorhaben am besten zu sein. Du kannst dann dessen ProgressChanged-Ereignis benutzen, um die Aktualisierung der GUI durchzuführen.
Einige Tipps dazu (und Links auf weitere Artikel) habe ich unter
Form friert ein trotz Verwendung des Backgroundworkers und Label-Refresh in einer Schleife verfasst.
Bau mal den BackgroundWorker in dein Programm ein und wenn du noch weitere Fragen dazu hast, kannst du dich gerne wieder melden.
|
|
Abayo 
Hält's aus hier
Beiträge: 4
|
Verfasst: Di 20.08.13 22:44
Hi ihr beiden
Danke für die schnelle Antwort!
@Th69: Thx, werd ich mir mal anschauen.
@IhopeonlyReader: Ich möchte in ienem Textfeld ne zahl eingeben und diese dann an mein Beagleboard senden. Dort wird die Zahl verarbeitet und wenn das fertig ist soll eine Antwort vom Beagleboard kommen was eingestellt wurde/rausgekommen ist. DAs wird dann genommen und in der GUI angezeigt indem ein image gedreht oder verschoben wird.
Da ich nicht genau weiß wann die verarbeitung fertig ist, muss ich ja entweder immer wieder die schnittstelle abfragen, oder eben ständig die schnittstelle auslesen bis eine antwort kommt.
|
|
IhopeonlyReader
      
Beiträge: 600
Erhaltene Danke: 23
Delphi 7 PE
|
Verfasst: Di 20.08.13 22:46
Oder du machst die "image verschieben procedure" noch in den thread und rufst sie synchroniziert auf
_________________ Sucht "neueres" Delphi
Wer nicht brauch was er hat, brauch auch nicht was er nicht hat!
|
|
Abayo 
Hält's aus hier
Beiträge: 4
|
Verfasst: Di 20.08.13 23:38
hmm.. wenn ich dich richtig verstehe meinst du das ich in der lese methode die ich dem 2ten thread übergebe auch gleich den aufruf/die reaktion für das verschieben der images der gui machen soll? Das ich also nach erhalt gleich darauf reagiere aus demselben thread und dann wieder auf lesen gehe?
Sind die elemente der WPF-GUI aus dem hauptthread auch im 2ten thread sichtbar/ansprechbar?
Ansonsten müsstest du deine Idee ein wenig mehr ausformulieren, da ich sonst nicht mitkomme was du meinst
(vor allem das "synchronisiert", habe da gerade mehrere ideen was gemeint sein könnte)
|
|
IhopeonlyReader
      
Beiträge: 600
Erhaltene Danke: 23
Delphi 7 PE
|
Verfasst: Mi 21.08.13 00:09
Ja, genau
Du kannst das image (notfalls die ganze Form) als pointer übergeben und dann im extra thread damit arbeiten..
Synchronize arbeiten meint, man ruft eine Prozedur ( ohne Parameter)
Von thread C im übergeordneten thread auf..
Thread C wartet auf die Ausführung...
Der übergeordnete thread wäre dein GUI-thread, hier würde die procedure aufgerufen, sobald der GUI thread an sich nichts zu tun hat ( wie es sein sollte)
P.S: da ich kein c direkt beherrsche kann ich mich nur allgemein halten.. Tut mir leid
_________________ Sucht "neueres" Delphi
Wer nicht brauch was er hat, brauch auch nicht was er nicht hat!
|
|
Th69
      

Beiträge: 4796
Erhaltene Danke: 1059
Win10
C#, C++ (VS 2017/19/22)
|
Verfasst: Mi 21.08.13 09:22
Hallo IhopeonlyReader,
nichts für ungut, aber ich glaube du verwirrst hier Abayo nur (In C# arbeitet man eben mit anderen Klassen und Vorgehensweisen als in Delphi mit der VCL - und mit C hat das rein gar nichts zu tun  ).
Für diesen Beitrag haben gedankt: FinnO
|
|
jfheins
      
Beiträge: 918
Erhaltene Danke: 158
Win 10
VS 2013, VS2015
|
Verfasst: Mi 21.08.13 12:00
Ich nehme jetzt mal an, du verwendest die SerialPort Komponente?
Und ist dein Problem ein blockieren beim senden, oder eines beim Warten?
Ich frage, weil ich da bereits etwas Erfahrung habe. Ich hatte allerdings keine Probleme mit dem Blockieren beim Senden. Das empfangen in dem Event geschieht ja ohnehin in einem separaten Thread. (Im Event COM_Port_DataReceived)
Falls deine Probleme beim senden sind, musst du entsprechend das senden in einen Thread auslagern. Und dann aber beim Zugriff auf den COM-Port nur mit lock{}. Ich würde dir empfehlen, eine extra Klasse zu erstellen, die die Kommunikation mit dem COM-Port abwickelt.
Einfrieren beim warten ist natürlich besonders unschön, das darf nicht passieren. Da musst du dein Programm etwas anpassen, damit man Befehle wegschicken kann (und währenddessen keinen Unsinn machen kann) und sobald die Antwort da ist wird diese angezeigt.
Falls du das senden nicht auslagern musst, reicht die TPL. (Die empfehle ich auch stets, der Backgroundworker ist ein bisschen ... angestaubt) Ansonsten stecke deine Päckchen in eine ConcurrentQueue<T> und lasse einen dezidierten Thread daraus lesen und verschicken. Das senden sollte dann natürlich nur noch durch diesen Mechanismus erfolgen.
|
|
Abayo 
Hält's aus hier
Beiträge: 4
|
Verfasst: Mi 21.08.13 12:54
Hi jfheins
Zur Abwicklung der Kommunikation benutze ich eine dll von FTDI, da ich einen FTDI USB-RS232-konverter zum Board hin verwende. Ich denke schon das die Serial Komponente verwendet wird, ist aber alles in einer eigenen Klasse von FTDI verpackt. In der PDF habe ich leider keine äquivalent zum COM_Port_DataReceived gefunden.
Mit dieser dll habe ich schon einmal gearbeitet, was auch gut lief bis auf das einfrieren der GUI (damals war das aber immer nur kurz während dem senden -> gelesen habe ich damals nicht)
Momentan bin ich noch in der theoretischen ausarbeitung und wie ich die Grundstruktur aufbauen möchte. Dabei ist mir eben aufgefallen dass ich probleme bekomme wenn ich keinen 2ten Thread verwende zum lesen (da ich ja nicht genau weiß wann die daten ankommen), andererseits habe ich aber bei einem 2ten thread das problem das ich die empfangenen daten irgendwie auch wieder zur gui kriegen muss.
TPL hab ich zwar schon gehört, muss ich mir aber erst noch anschauen. ich habe aber die vermutung das tpl in meinem fall eher dasselbe ist wie "mit Kanonen auf Spatzen schießen" ^^
werde ich aber mal mit weiterverfolgen die idee.
Gestern Nacht ist mir noch eine Idee gekommen mit dem Backgroundworker. Scheinbar kann ich die empfangenen Daten als ein Object an das ProcessChanged-Event schicken, was dann wieder im Hauptthread der GUI ist (oder?). Das wäre dann schonmal eine Möglichkeit wie ich die empfangenen daten an die GUI bekomme.
Zum Senden könnte ich dann jeweils einen neuen thread starten und beenden. Das Senden hängt ja eh nur von meinen eingaben auf der GUI ab.
|
|
jfheins
      
Beiträge: 918
Erhaltene Danke: 158
Win 10
VS 2013, VS2015
|
Verfasst: Mi 21.08.13 20:19
Probiere es mal mit der SerialPort Komponente. Wenn du nur kommunizieren möchtest, sollte das ja reichen. Mit der FTDI-Klasse kenne ich mich leider nicht aus und kann dir da keine Hilfestellung leisten
Allerdings sollte es auch mit der FTDI Komponente gehen. Dann ebenso die ganze Kommmunikation in einen Thread auslagern und ggf. mit lock{} synchronisieren.
|
|