2009-07-17 11 views
3

Ich habe überall gesucht und ich kann das nicht herausfinden. Ich arbeite an einer Winforms-Benutzeroberfläche, die große Mengen von Zeilen zieht, die ich in einem DataGridView anzeigen muss. Ich habe bereits alles über das Einschränken von Zeilenzählungen und Paging gelesen und es gibt absolut keinen guten Weg, dies zu tun. Im Grunde arbeite ich an dem TargetDataViewer-Steuerelement des Extended Events Manager für SQL Server 2008, das ich auf Codeplex geschrieben habe.Loading DataTable Langsam, wenn DataGridView.Datasource gebunden

http://extendedeventmanager.codeplex.com/

Ich bin begrenzt auf das, was ich auf der Grundlage der spezifischen Ziel tun können und wie es Daten präsentiert. Ich versuche, die Daten, die von einem Ziel gelesen wurden, in das DataGridView zu streamen, ähnlich wie Profiler oder SQL Server Management Studio beim Streamen Daten anzeigt. Ich schrieb viel Code um und ließ einen BackgroundWorker Daten ziehen und verarbeitet es in eine DataTable. Wenn ich DataGridView.DataSource = DataTable nicht einstelle, kann ich 300K + Datenzeilen in ein paar Minuten in die DataTable laden, es läuft wirklich schnell. Sobald ich die DataTable zur DataSource hinzufüge, wird sie langsam bis fast zum Stillstand (statt ein paar Minuten können die gleichen 300K Zeilen eine halbe Stunde dauern).

Ich weiß, dass das Problem nicht meine Verarbeitung Code ist, ist es spezifisch an die DataGridView.DataSource gebunden, und ich habe Timing-Code, um dies zu beweisen. Ich kann mir nicht vorstellen, wie ich das umgehen soll. Für die Leistung kann ich das Steuerelement spät an die DataTable binden, nachdem die Daten geladen sind, aber das ist eine wirklich beschissene Benutzererfahrung. Ich sehe viele Leute, die sich über die Performance-Auswirkungen von DataGridView beim Laden von Daten beschweren, so dass dies nur eine Einschränkung sein kann, mit der ich feststecke? Irgendwelche Ideen?

+0

Hoffe ich nicht dumm klingen. Aber hilft DataReader in diesem Fall? – shahkalpesh

+0

Nein, ich habe einen offenen SqlDataReader, der für jede Zeile ein nicht schemagebundenes XML-Dokument zieht. Dann habe ich Code, der dieses XML in ein Objekt [] parst, das als Parameter an die LoadRow() -Methode übergeben wird. –

Antwort

12

Überlegen Sie, was passiert, wenn Sie ein ungebundenes DataTable mit einer Zeile aus einem DataReader füllen: Ein DataRow wird vom DataReader erstellt, bevölkert, und zu der Rows Sammlung. Wenn Sie die Bindung dann erstellen, zieht die DataGridView Daten aus der Tabelle und erstellt die Ansicht auf dem Bildschirm.

Was passiert, wenn Sie eine DataTable auffüllen, deren Bindung an die DataGridView aktiviert ist? Eine ganze Menge an Event-Handling. Jedes Mal, wenn Sie eine gebundene Eigenschaft ändern, wird das Ereignis mit geänderter Eigenschaft ausgelöst und das gebundene Steuerelement verarbeitet es. Das passiert nicht 300.000 mal, es passiert 300.000 Mal für jede Spalte.

Was passiert, wenn Sie diese Option deaktivieren und nur gelegentlich die gebundene Steuerung aktualisieren? Sehen Sie sich diese Methode an:

Sie müssen ResetBindings aufrufen, um die Aktualisierung des gebundenen Steuerelements zu erzwingen. Dies kostet Zeit, da Sie die Kosten für die Erstellung der DataGridViewRow Objekte nicht umgehen können, aber das Entfernen der Ereignisse ist eine deutliche Verbesserung. Wenn ich eine 10-spaltige 10000-Zeile DataTable, die an eine DataGridView gebunden ist, auf meinem Computer bevölkert, dauert es 2900 Millisekunden. Wenn ich die Datenbindung die ganze Zeit ausgeschaltet lasse, dauert es 155 Millisekunden. Wenn ich die Bindungen alle 500 Zeilen zurücksetze, dauert es 840 Millisekunden.

Natürlich, wenn ich 300.000 Row-Tabelle auffüllen würde, würde ich die Bindungen nicht alle 500 Zeilen zurücksetzen; Ich würde es wahrscheinlich einmal bei der Markierung mit 500 Zeilen tun und es dann ausschalten, bis die Operation abgeschlossen ist. Aber selbst wenn Sie dies tun, müssen Sie immer wieder Application.DoEvents anrufen, damit die Benutzeroberfläche auf Ereignisse reagieren kann.

bearbeiten

nie, dass etwas über Application.DoEvents ausmacht; Sie müssen das nicht tun, wenn Sie die Tabelle in einer Hintergrundaufgabe auffüllen.

Sie müssen jedoch sicherstellen, dass Sie die Bindungen in der ProgressChanged Event-Handler zurücksetzen, und nicht in der DoWork Methode. Und Sie werden eine Welt der Verletzung erleben, wenn Sie tatsächlich den Benutzer bearbeiten Daten in der gebundenen DataGridView während Sie seine Datenquelle in einem anderen Thread bevölkern.

+0

Sie mein guter Herr, sind jetzt mein Held für heute. Dies ist genau das, was ich brauchte und perfekt funktionierte. Ich schrieb eine benutzerdefinierte Klassifizierungsmethode, die einen Bool zurückgibt, ob die BindingSource basierend auf der aktuellen Datenmenge in der DataTable aktualisiert werden sollte, damit sie schneller aktualisiert wird, um die Zeilen zu rendern, und umso langsamer, je größer die Daten sind, um die Aktualisierung zu balancieren mit Leistung. Es ist nicht perfekt, aber es ist viel besser als vorher. –

+2

Freut mich zu hören. Ich denke, dass Sie immer noch eine Menge Probleme mit einer UI-Kontrolle haben werden, die an eine Datenquelle mit 300K-Datensätzen gebunden ist. Das scheint eine verrückte Menge an Daten zu sein, die man mit den eingeschränkten Tools von DataGridView zu bewältigen versucht. –

Verwandte Themen