C# Threadzugriff auf GUI

ali7566

Lieutenant
Registriert
Feb. 2007
Beiträge
980
Hallo,

schreibe zur Zeit eine Software die über RS232 Schnittstelle werte einliest und in eine CSV Datei speichert. Soweit nichts wildes und die Software ist eigentlich auch schon fertig aber es gibt da noch ein Problem.

Da nach dem starten der Software eine While schleife läuft die Byte-weise einliest blockiert mir diese komplett die GUI, da der aktuelle Thread ja nur beim einlesen ist...Logisch.

Daraufhin habe ich einen Thread erzeugt der sich um das einlesen kümmert und die Daten noch in das DataGrid einfügt. Da der Thread jedoch nicht der Erzeuger des DataGrid gewesen ist musste ich folgenden Code nutzen um den Thread das Recht zu geben auf das Steuerelement zuzugreifen:

Code:
           if (gridMesswerte.InvokeRequired)
            {
                gridMesswerte.Invoke(new MethodInvoker(dataReading));
                return;
            }

Danach kam die Exception zwar nicht mehr und die dazugehörigen Methode dataReading welche sich um das Einlesen kümmert Arbeitet dann auch aber die GUI blockiert immer noch.

Was mache ich da falsch?

Um den Thread anzuwerfen mache ich übrigens folgendes:

Code:
    controlThread = new Thread(new ThreadStart(dataReading));

    controlThread.Start();


Gruß Ali.
 
Hi,

ein BackGround-Worker wäre in diesem Fall vielleicht eine Idee. Dabei musst du dich nicht selbst um das Threading und die Zugriffe kümmern. Einfach mal Google fragen, gibt sehr viele Beispiele, das wäre in deinem Fall glaube ich die einfachste Lösung.

VG,
Mad
 
Sehr gut...werde ich gleich mal gucken. Danke dir.

Gruß Ali.
 
Und gleich mit einprägen: Daten erst gesammelt in die GUI verfrachten, sonst blockt diese ebenso wieder, da ja ständig der BackgroundWorker die GUI mit Daten füttert.
 
Also, wenn ich dich nicht falsch verstanden habe liegt dein Problem darin:

In der Methode dataReading (bzw. in dem entsprechenden Thread) hast du bisher irgendwo diese Codezeilen, wenn ich dich richtig verstanden habe:
Code:
if (gridMesswerte.InvokeRequired)
    {
    gridMesswerte.Invoke(new MethodInvoker(dataReading));
    return;
    }

Allerdings ergibt das keinen Sinn. Statt die Methode dataReading zu invoken musst du eine neue Methode updateGrid (oder so) erstellen und diese normal aufrufen:
Code:
private void updateGrid()

if (gridMesswerte.InvokeRequired)
    {
    gridMesswerte.Invoke(new MethodInvoker(updateGrid));
    return;
    }

// hier Grid updaten
}

In der Methode updateGrid updatest du dein Grid entsprechend, das passiert dann auch in dem Thread der GUI.

Weitere Informationen dazu kannst du auf dieser Seite finden (z.B. auch wie du das ganze parametrisiert machen kannst): http://www.mycsharp.de/wbb2/thread.php?threadid=33113

Ich hoffe das hilft dir weiter (auch wenn meine Antwort etwas knapp gehalten ist)
 
Zuletzt bearbeitet: (Codebeispiel expliziter gemacht)
Hi,

und gleich noch eine kleine Anmerkung: wenn es "modernes" .NET ist schaue dir mal "async await" an. Ist quasi die Wachablösung für die Backgroundworker. Hier z.B. eine interessante Diskussion.

VG,
Mad
 
Ich habe gerade meinen letzten Post etwas expliziter gemacht, da ich bim durchlesen bemerkt habe, das man ihn auch falsch verstehen könnte. Zusätzlich habe ich dir auf die schnelle ein kleines Beispiel erstellt, damit es noch klarer wird, was ich meine:

Code:
        private int count = 0;

        private void UpdateTextbox()
        {
            if (textBox1.InvokeRequired)
            {
                textBox1.Invoke(new MethodInvoker(UpdateTextbox));
                return;
            }
            textBox1.Text = count.ToString();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            Thread t = new Thread(CountUp);
            t.Start();
        }

        private void CountUp()
        {
            for (int i = 0; i < 10000; i++)
            {
                count = i;
                Thread.Sleep(1000);
                UpdateTextbox();
            }
        }

Die GUI hat genau einen Button und eine TextBox. Das mit der globalen Variable finde ich nicht sooo schön, besser wäre es mit Parameter beim Aufruf der Methode.
 
Hi, und danke für die rasche Hilfe....Vielen dank vor allen Phoenixz, hat mich zu meinem Ziel gebracht.

TPL hatte ich mir auch schon angeguckt aber ich war mir nicht so sicher ob es in VC# 2010 schon weitgehends ausgebaut ist. Da ja in .Net 4.5 schon einges mehr in der Api von TPL zu stecken scheint.

Gruß Ali.
 
Zurück
Oben