Laden...

DataGridView aus Thread aktualisieren - sehr langsam

Erstellt von tho.tull vor 11 Jahren Letzter Beitrag vor 11 Jahren 2.299 Views
T
tho.tull Themenstarter:in
3 Beiträge seit 2013
vor 11 Jahren
DataGridView aus Thread aktualisieren - sehr langsam

Hallo NG,

ich möchte gerne in einem DataGridView Daten automatisch aktualisieren und anzeigen. Die geänderten Werte werden in einem separaten Thread ermittelt und in ein DataView geschrieben, welches auch als DataSource für das DataGridView fungiert.

Die Änderungen werden im DataGridView zwar angezeigt aber das Ganze läuft sehr langsam ab. Wie kann man den Vorgang beschleunigen. Der Code sieht wie folgt aus:

DataView dvDataGrid1;
Thread thrCom;

public delegate void EditDataGridCallback(DataView dvDataGrid);

private void button1_Click(object sender, EventArgs e)
{
        thrCom = new Thread(new ThreadStart(StartThread));
        thrCom.Start();
}

void StartThread()
{
        while (true)
        {
                foreach(DataRowView row in dvDataGrid)
                {
                        dvDataGrid1 = clsCom.dvReadValue(dvDataGrid);
                        dataGridView1.Invoke(new EditDataGridCallback(this.EditDataGrid), dvDataGrid1);
                        Thread.Sleep(1000);
                }
        }
}
private void EditDataGrid(DataView dvDataGrid)
{
        dataGridView1.DataSource = dvDataGrid1;
}

Vielen Dank vorab.

Gruß
Thomas

Edit: Nun bekomme ich auch noch eine "InvalidOperationException" mit der Meldung, daß das Object bereits an anderer Stelle verwendet wird. Das Programm springt dazu in die Programm Klasse zurück und ich kann nicht erkennen, wo dieser Fehler ausgelöst wird!

Besten Dank.

C
2.121 Beiträge seit 2010
vor 11 Jahren

Du weist dem Grid jede Sekunde eine neue DataSource zu?

Außerdem ist das Sleep innerhalb der Schleife. Da passiert also pro Sekunde nur ein Durchlauf, ist es das was du als langsam bemerkst?

T
tho.tull Themenstarter:in
3 Beiträge seit 2013
vor 11 Jahren

Nein. Die geänderten Daten werden zeilenweise langsam ins DataGrid gezeichnet. Allerdings nur wenn sehr viele Werte geändert werden. Das größere Problem ist jetzt allerdings, daß ich nicht erkennen kann von wo aus das Programm abstürzt!

Vielen Dank.

C
2.121 Beiträge seit 2010
vor 11 Jahren

Was bedeutet zeilenweise langsam?

Gibts zu der Exception einen StackTrace?
Du hast die Methode EditDataGrid mit einem Parameter versehen, der allerdings nirgends genutzt wird. Kann das damit zusammenhängen?
Ich halte es für kritisch dass du jede Sekunde eine neue View zuweist. Vielleicht überholt sich da irgendwas, dass die Daten schneller kommen als die GUI damit klar kommt.

T
tho.tull Themenstarter:in
3 Beiträge seit 2013
vor 11 Jahren

Wie kann ich denn verhindern, daß es hier einen Überlauf gibt? Ich möchte ja die Werte aus einem Thread innerhalb des DataGrids aktualisieren (allerdings nur eine Zelle je Reihe - wäre es sinnvoller nur die Zellen in eine Schleife zu aktualisieren?).

Auch wenn ich im Thread lediglich das DataView aktualisiere, und den Invoke Befehl auf das DataGrid auskommentiere wird das DataGridView zunächst aktualisiert. Nach Kurzer Zeit bekomme ich dann erneut diese Fehlermeldung.

Also Frage ist, wie kann ich diese Daten zyklisch Aktualsieren?

Besten Dank

C
2.121 Beiträge seit 2010
vor 11 Jahren

Schalte erst mal ein dass der Debugger bei allen geworfenen Exceptions anhalten soll. Das könnte dir schon viel Info geben.

Ich würde den Inhalt der DataView ändern. Nicht jede Sekunde eine komplett neue View ins Grid hängen. Das muss dann alles bisherige löschen und alles komplett neu übernehmen.
Dazu müsstest du natürlich dvReadValue überarbeiten. Wenn du immer alle Daten neu bestimmst, müssten jetzt nur noch die Änderungen in die bestehende View eingebaut werden.

Was ich auch noch grad erst sehe, du gehst jede Zeile in der View durch und bestimmst für jede Zeile den kompletten Datenbestand der View neu. Da passt noch was nicht, überdenke das nochmal. "row" wird nirgends verwendet. Wahrscheinlich hast du hier noch einen krassen Denkfehler drin.

4.221 Beiträge seit 2005
vor 11 Jahren
  
DataView dvDataGrid1;  //<--hier ist dvDataGrid1 deklariert  
  
void StartThread()  
{  
        while (true)  
        {  
                foreach(DataRowView row in dvDataGrid)  
                {  
                        dvDataGrid1 = clsCom.dvReadValue(dvDataGrid); // <-- hier wird die Variable dvDataGrid1 aus einen Thread aktualisiert (das ist ganz böse)  
                        dataGridView1.Invoke(new EditDataGridCallback(this.EditDataGrid), dvDataGrid1);  
                        Thread.Sleep(1000);  
                }  
        }  
}  
private void EditDataGrid(DataView dvDataGrid)  
{  
        dataGridView1.DataSource = dvDataGrid1; // <-- hier wird die Variable dem DataGridView1 zugewiesen (im UI-Thread)  
}  

Gebundene Objekte sollten NIE aus einem Nicht-UI-Thread verändert werden !

Deklarier die Variable innerhalb des for each...

Das ist dann zwar immer noch langsam... aber Deine Exceptions sollten dann weg sein.

Gruss
Programmierhans

Früher war ich unentschlossen, heute bin ich mir da nicht mehr so sicher...

49.485 Beiträge seit 2005
vor 11 Jahren

Hallo Programmierhans,

richtig ist, dass man auf gebundene Daten nur aus dem GUI-Thread zugreifen darf. Allerdings führt das Ändern der Variable dvDataGrid1 für sich alleine genommen zu keinem threadübergeifenden Zugriff. Und es ist für einen threadkonformen Zugriff auch egal, wo die Variable deklariert ist. Selbstverständlich voraussetzt es würde in EditDataGrid wie vermutlich beabsichtigt der Parameter als Quelle der Zuweisung verwendet werden statt der "gloablen" Variable. Und richtig ist natürlich, dass dies aufgefallen wäre, wenn die Variable stattdessen lokal in StartThread deklariert worden wäre (ob innerhalb von foreach oder nicht, spielt dagegen hier keine Rolle).

herbivore

1.378 Beiträge seit 2006
vor 11 Jahren

Was ich nicht verstehe ist, für was du über alle Rows iterierst, wenn du im Endeffekt die Row selber nie benutzt bzw. manipulierst. Du bekommst aus deiner Methode clsCom.dvReadValue(dvDataGrid); eine neue DataView und weißt diese zu. Das sollte doch mit einem einfachen Statement ausreichen oder?


DataView dvDataGrid1;

private void button1_Click(object sender, EventArgs e)
{
        dvDataGrid1 = clsCom.dvReadValue(dvDataGrid);
        dataGridView1.DataSource = dvDataGrid1;
}

Lg, XXX

4.221 Beiträge seit 2005
vor 11 Jahren

richtig ist, dass man auf gebundene Daten nur aus dem GUI-Thread zugreifen darf. Allerdings führt das Ändern der Variable dvDataGrid1 für sich alleine genommen zu keinem threadübergeifenden Zugriff.

Ja da gebe ich Dir recht. Wenn nur die bestehende DataView manipuliert würde, dann würden Events einlaufen welche nicht im UI-Thread wären... und das wäre übel...

Aber trotzdem sehr unübliches Konstrukt.

Früher war ich unentschlossen, heute bin ich mir da nicht mehr so sicher...