Hallo zusammen,
ich versuche seit Wochen, eine Datei zeilenweise mit C# (SharpDevelop)an
einen Mikrocontroller zu senden und auf die Antwort zu warten.
Der Programmablauf ist in etwa folgender: Beim Klick auf Button1 wird
folgendes gestartet:
Open_File();
Open_SerialPort1();
foreach line in file
{
create_message(); //Zeile in Datenpaket packen (mit Adresse und
Prüfsumme)
send_message(); //Nachricht absenden
delay(); //warten bis ein Timer abgelaufen ist (ca. 500ms)
check_answer(); //Prüfen, ob erwartetes Antwortpaket empfangen wurde
}
Da das Antwortpaket schon mal ne halbe Sekunde auf sich warten lässt,
warte ich immer so lange, bis ich die empfangenen Antwortdaten prüfe.
Das kostet unnötig Zeit, weil die Antwort meist schon nach 20 ms da ist.
Des Weiteren blockiert die Senderoutine mein Formular, wo ich gerne eine
Uhr und einen Progressbalken mit laufen lassen würde. Jetzt habe ich
schon verstanden, dass ich das mittels Threading lösen muss. Aber was
muss in welchen Thread? Und vor allem wie?
Filename und Portparameter sowie Adressdaten stehen in verschiedenen
TextBoxen. Diese muss die Senderoutine ja auslesen (oder sollte ich sie
ihr übergeben?)
Sollte ich jew. einen Thread zum Senden, Empfangen und Dateilesen
machen, oder alles in einem Thread machen. Und wie kann ich die
Empfangsdaten prüfen, ohne generell so lange zu warten?
Ich weiß, das ist ziemlich viel auf einmal, aber vielleicht kann mir ja
trotzdem jemand weiterhelfen.
Achja – prinzipiell funktioniert das Programm – aber ewig langsam und
mit blockiertem System (andere Programme wollen auch nicht mehr so
richtig während der Laufzeit und der Lüfter dreht auf Hochtouren)
Vielen Dank, Thomas
Hi Thomas,
Thomas wrote:
> Hallo zusammen,>> ich versuche seit Wochen, eine Datei zeilenweise mit C# (SharpDevelop)an> einen Mikrocontroller zu senden und auf die Antwort zu warten.> Der Programmablauf ist in etwa folgender: Beim Klick auf Button1 wird> folgendes gestartet:>> Open_File();> Open_SerialPort1();> foreach line in file> {> create_message(); //Zeile in Datenpaket packen (mit Adresse und> Prüfsumme)> send_message(); //Nachricht absenden> delay(); //warten bis ein Timer abgelaufen ist (ca. 500ms)> check_answer(); //Prüfen, ob erwartetes Antwortpaket empfangen wurde> }>> Da das Antwortpaket schon mal ne halbe Sekunde auf sich warten lässt,> warte ich immer so lange, bis ich die empfangenen Antwortdaten prüfe.> Das kostet unnötig Zeit, weil die Antwort meist schon nach 20 ms da ist.> Des Weiteren blockiert die Senderoutine mein Formular, wo ich gerne eine> Uhr und einen Progressbalken mit laufen lassen würde. Jetzt habe ich> schon verstanden, dass ich das mittels Threading lösen muss. Aber was> muss in welchen Thread? Und vor allem wie?
Packe den obigen Code-Abschnitt komplett in einen Thread. Zum Threading
gibt's bei MS entsprechende Artikel:
http://www.microsoft.com/germany/msdn/library/net/VerwendenVonThreads.mspx?mfr=truehttp://msdn2.microsoft.com/en-us/library/e1dx6b2h(VS.85).aspx> Filename und Portparameter sowie Adressdaten stehen in verschiedenen> TextBoxen. Diese muss die Senderoutine ja auslesen (oder sollte ich sie> ihr übergeben?)
Letzteres. Software sollte strikt aufgeteilt sein in Oberfläche und
Datenmodell. Siehe hierzu das MVC Architekturmodell, z.B. in Wikipedia.
> Sollte ich jew. einen Thread zum Senden, Empfangen und Dateilesen> machen, oder alles in einem Thread machen.
Ein Thread.
> Und wie kann ich die> Empfangsdaten prüfen, ohne generell so lange zu warten?
ReadTimeout Property beim SerialPort Objekt setzen, z.B. auf 500ms.
> Ich weiß, das ist ziemlich viel auf einmal, aber vielleicht kann mir ja> trotzdem jemand weiterhelfen.> Achja – prinzipiell funktioniert das Programm – aber ewig langsam und> mit blockiertem System (andere Programme wollen auch nicht mehr so> richtig während der Laufzeit und der Lüfter dreht auf Hochtouren)
Ich weiß nicht wirklich, was Dein delay() Methode veranstaltet. Aber
nachdem Du schreibst, daß Dein Rechner auf Vollast läuft, schätze ich
mal, daß Du dort einen sogenannten Busy-Wait durchführst (verbraten von
CPU-Zeit). Absolut tödlich auf Multiprocessing Systemen. Lasse den
delay() Aufruf komplett weg und verwende, wie bereits oben geschrieben
den ReadTimeout.
> Vielen Dank, Thomas
Grüße
Markus
Hallo Markus,
vielen Dank für Deine Tips. Ich werde vermutlich morgen mal sehen, wie
weit ich komme. Bin gerade erstmal dabei das Programm so umzuschreiben,
dass ich kaum noch globale Variablen brauche und alles mit Übergabe und
Rückgabeparametern erschlage.
Mit dem Delay hast Du recht. Ich setze eine Hilfsvariable, starte einen
Timer und der setzt sie zurück. Die Zeit schlage ich mit >>
while(hifsvariable); << tot. War mir schon klar, dass das nicht OK ist.
Werde mal sehen, wie ich das anders löse...
Gruß, Thomas
wenn schon warten dann einfach mit Thread.Sleep(500); Und zum
Progressbar gibts auch Beispiele in der C# Doku. Wenn die Kommunikation
in einen seperaten Thread verlegt wird dann wirst du noch auf das
Problem stossen das du aus dem Worker-Thread nicht auf Steuerelement in
deinem Dialog zugreifen darfst. Dafür solltest du die Invoke-Beispiele
übernehmen.
Hi Thomas,
Thomas wrote:
> Hallo Markus,>> vielen Dank für Deine Tips. Ich werde vermutlich morgen mal sehen, wie> weit ich komme. Bin gerade erstmal dabei das Programm so umzuschreiben,> dass ich kaum noch globale Variablen brauche und alles mit Übergabe und> Rückgabeparametern erschlage.> Mit dem Delay hast Du recht. Ich setze eine Hilfsvariable, starte einen> Timer und der setzt sie zurück. Die Zeit schlage ich mit >>> while(hifsvariable); << tot. War mir schon klar, dass das nicht OK ist.> Werde mal sehen, wie ich das anders löse...
Wie ich bereits oben geschrieben habe, lasse den Aufruf von delay()
komplett weg. Du mußt das Lesen vom COM-Port so aufsetzen, daß Du z.B.
auf ein Zeichen mit Timeout wartest und wenn das Zeichen ankommt, mit
Thread.Sleep(...) nochmals ein paar Millisekunden wartest, damit der
Rest der Sendung übertragen werden kann. Die Zeit solltest Du über das
Datenvolumen und die Baudrate berechnen können. Dann ermittelst Du mit
SerialPort.BytesToRead, wieviel Daten anliegen und liest diese mit
SerialPort.Read() ein. Dein delay() ist dabei völlig
überflüssig weil das Warten entweder beim Lesen vom Com-Port oder über
Thread.Sleep() stattfindet. Beide Arten zu Warten sind
multi-processing-verträglich.
>> Gruß, Thomas
Grüße
Markus