Datenübergabe an GUI-Thread

Gast #4853336
Lesenswert?
• ▲
▼
Hallo,
ich habe einen Thread, der Daten von der seriellen Schnittstelle 
einliest.
Diese sollen auf der Console ausgegeben werden.
Die Ausgabe soll im eigenen Thread stattfinden, um den Einlsese-Thread 
nicht zu blockieren.
Dieser Ansatz funktioniert nicht ganz so toll:
1
    while (_continue)
2
    {
3
      try
4
      {
5
        if (_serialPort.BytesToRead > 0) {
6
          var ret = _serialPort.Read(arr,0,_serialPort.BytesToRead);
7
          if (ret > 0) {
8
            this.BeginInvoke((MethodInvoker) delegate {
9
              for (int i=0;i<ret;i++) {
10
                Console.WriteLine("{0,5}:{1,2:X}",cnt,arr[i]);
11
                cnt++;
12
              }
13
            });
14
          }
15
        }
16
      }
17
      catch (TimeoutException) { }
18
    }


Das Problem ist, wenn die Ausgabe-Routine verzögert ist, dann gibt der 
WriteLine nicht die Werte (arr[]) aus, mit der das delegate aufgerufen 
wurde, sondern die bereits aktualisierten.
D.h. werden die Werte 1,2,3,4,5 empfangen, so gibt er z.B. 1,2,4,4,5 
aus.
Ich hatte schon arr[] zwischengespeichert, damit die ursprünglichen 
Werte für das delegate erhalten blieben, aber das funktioniert auch 
nicht.
Was tun?
#4855917
Lesenswert?
• ▲
▼
Mit C# kenne ich mich nicht aus. Aber sobald du mit mehreren Threads 
arbeitest, musst du dich auch mit IPC (inter process communication) und 
Mutexe befassen.

Was du da vor hast ist eigentlich ein typischer Anwendungsfall für einen 
Ringpuffer oder ein FIFO, auf den immer nur ein Thread zur Zeit 
zugreifen darf.

Trivial ist des jedenfalls nicht.
Gast #4856029
Lesenswert?
• ▲
▼
Moin,

tja, das Leid mit den Threads^^

Der Weg, den du gehst ist übrigens ungewöhnlich. Die Klasse SerialPort 
kann bereits asyncron lesen. Da brauchst du keinen eigenen Thread für 
aufmachen.
1
SerialPort myPort;
2

3
void init()
4
{
5
    myPort = new SerialPort("com1");
6
    myPort.DataReceived += dataReveived;
7
    myPort.Open()
8

9
}
10

11

12
StringBuilder dataStorage = new StringBuilder();
13
Object lockObject = new Object();
14
void dataRecevied(Object sender, SerialDataReceivedEventArgs e)
15
{
16
    // wird aufgerufen, wenn Daten am Port eintrudeln.
17
    
18
    lock(lockObject)
19
    {
20
        var readData = myPort.ReadExisting();
21
        dataStorage.Append(readData);
22
        printNewData(readData);    
23
    }
24
}

Ich hab das ganze natürlich vereinfacht dargestellt.

Das hat für dich vor allem den Vorteil, dass beim Eintrudeln von Daten 
ein neuer Aufruf der Methode erfolgt. Will sagen, die lokalen Variablen 
werden nicht Überschrieben. Egal, ob die ausgegeben werden oder nicht.

Ich weiß grad gar nicht, was ich noch schreiben soll. Na ja, wenn du 
Fragen hast, dann raus damit :)

Antwort schreiben

Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt. Bitte hier nur auf die ursprüngliche Frage antworten, für neue Fragen einen neuen Beitrag erstellen.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.