Ich ändere ein Windows-Formular, damit Daten im Hintergrund geladen werden können, während die Benutzeroberfläche reaktionsfähig bleibt. Die Daten benötigen spürbare Zeit sowohl zum Abrufen als auch zum Binden. Im Idealfall würde ich beides im Hintergrund tun, aber es gibt einige Unklarheiten darüber, welche Art von UI-Updates ich im Hintergrund machen soll (wie außerhalb des Hauptthreads). Ein solides Beispiel, das Datenabruf und Datenbindung im Hintergrund zeigt, wäre sehr hilfreich.Reaktion der WinForms-Benutzeroberfläche beim Umgang mit "schweren" Daten
Antwort
Der Abruf kann und soll, werden zu einem Hintergrundthread abgeschoben - aber es gibt einige Muster alles an Ort und Stelle zu setzen.
Im Grunde werden Sie einen Hintergrund-Thread zum Abrufen der Daten starten, sobald es fertig ist, muss es wieder in den UI-Thread zusammengeführt werden, um die tatsächlichen UI-Updates durchzuführen (UI-Updates über Threads sind schlecht schlecht schlecht).
ist es drei grundlegende Arten von Hintergrund Threading für Sie
- die einfachste/meist begrenzt (und schrullige IMO) zu erkunden, sind die Background Komponente
- mit Delegierten und deren BeginInvoke()/EndInvoke() -Methoden bieten eine gute Balance von Leichtigkeit und Flexibilität (und Threadpool Threads verwenden)
- mit Rohfaden Objekte bietet die Kontrolle, sind aber langsamer zu Setup als Threadpool Threads
Persönlich lehne ich mich der Delegierten-Option zu; Sie sind ziemlich einfach zu bearbeiten, sobald Sie das Muster ablegen. Der BackgroundWorker scheint vorne nett zu sein, hat aber einige Probleme und fehlende Installationen, die es mühsamer machen, mit der Arbeit zu beginnen, als Sie erwarten würden. Lassen Sie mich eine kurze Probe des Delegate-Ansatzes machen; Ich werde in Kürze aktualisieren ...
bearbeiten
Hier ist ein Code, dann ist es in VB aber sollte leicht genug sein, zu transkribieren, wenn Sie ein C# Kerl sind. Sie haben noch ein paar Optionen, wie sich der Hintergrund-Thread verhalten soll, also gibt es hier zwei Beispiele. Non-Blocking ist mein Favorit, aber wenn Sie es in vorhandenen Code anpassen, dann könnte die Blockierung für Sie einfacher sein.
Non-blocking, die Callback-Methode (GetData_Complete) auf dem UI-Thread aufgerufen werden, wenn der Hintergrund-Thread abgeschlossen ist
Sub Main()
Console.WriteLine("On the main thread")
Dim dataDelegate As New GetDataCaller(AddressOf GetData)
Dim iar As IAsyncResult
' Non-blocking approach using a callback method
iar = dataDelegate.BeginInvoke(AddressOf GetData_Complete, Nothing)
End Sub
Private Delegate Sub GetData_CompleteCaller(ByVal iar As IAsyncResult)
Private Sub GetData_Complete(ByVal iar As IAsyncResult)
If InvokeRequired Then
Dim invokeDelegate As New GetData_CompleteCaller(AddressOf GetData_Complete)
Invoke(invokeDelegate, New Object() {iar})
Exit Sub
End If
' Downcast the IAsyncResult to an AsyncResult -- it's safe and provides extra methods
Dim ar As System.Runtime.Remoting.Messaging.AsyncResult = DirectCast(iar, System.Runtime.Remoting.Messaging.AsyncResult)
Dim dataDelegate As GetDataCaller = DirectCast(ar.AsyncDelegate, GetDataCaller)
Dim result As String = dataDelegate.EndInvoke(iar)
Console.WriteLine("On the main thread again, background result is: " + result)
End Sub
Private Delegate Function GetDataCaller() As String
Private Function GetData() As String
Console.WriteLine("On the background thread!")
For index As Integer = 0 To 2
Console.WriteLine("Background thread is working")
Next
Return "Yay, background thread got the data!"
End Function
Blocking Sub Main()
Console.WriteLine("On the main thread")
Dim dataDelegate As New GetDataCaller(AddressOf GetData)
Dim iar As IAsyncResult
' blocking approach; WaitOne() will block this thread from proceeding until the background thread is finished
iar = dataDelegate.BeginInvoke(Nothing, Nothing)
iar.AsyncWaitHandle.WaitOne()
Dim result As String = dataDelegate.EndInvoke(iar)
Console.WriteLine("On the main thread again, background result is: " + result)
End Sub
Private Sub GetData_Complete(ByVal iar As IAsyncResult)
' Downcast the IAsyncResult to an AsyncResult -- it's safe and provides extra methods
Dim ar As System.Runtime.Remoting.Messaging.AsyncResult = DirectCast(iar, System.Runtime.Remoting.Messaging.AsyncResult)
Dim dataDelegate As GetDataCaller = DirectCast(ar.AsyncDelegate, GetDataCaller)
Dim result As String = dataDelegate.EndInvoke(iar)
Console.WriteLine("On the main thread again, background result is: " + result)
End Sub
Private Delegate Function GetDataCaller() As String
Private Function GetData() As String
Console.WriteLine("On the background thread!")
For index As Integer = 0 To 2
Console.WriteLine("Background thread is working")
Next
Return "Yay, background thread got the data!"
End Function
Aktualisieren Sie die Benutzeroberfläche niemals von einem Hintergrundthread. Nachdem Sie Ihre Daten vom Server abgerufen haben, rufen Sie den UI-Thread erneut auf, um die UI-Steuerelemente oder das Dataset zu aktualisieren, an die Ihre UI gebunden ist.
Die Verwendung von BackgroundWorker hilft in diesem Fall nur die Ereignisse zu verkabeln.
HTH
Phil‘
Das Laden (wie beim "Abrufen aus der Datenquelle") kann trivial sein, egal ob Sie Delegaten, Hintergrundarbeiter oder ein anderes Protokoll verwenden.Die Bindung scheint jedoch schwierig, da es kaum Kontrolle gibt, zumindest in den meisten datengebundenen Steuerelementen. Sie können Daten asynchron abrufen, aber sobald Sie sie bereit haben, können Sie sie im Hintergrund in ein großes Raster einspeisen. Ist das deine Frage? Wenn ja, können Sie entweder:
- erstellen (oder Unterklasse) Ihre Ansicht Steuerelement, die Schnittstellen für asynchrone Last;
- implementieren Sie eine seitenweise Ansicht, die nur N Datensätze gleichzeitig zeigt, so dass die Benutzeroberfläche beim Abrufen/Formatieren von Datensätzen nicht blockiert wird.
- 1. Umgang mit Gigabyte Daten
- 2. Android: Umgang mit unerwarteten Internet-Verbindung beim Herunterladen von Daten
- 3. Probleme beim Umgang mit Orientierungsänderungen
- 4. Umgang mit Daten von httpclient
- 5. Umgang mit Daten in FTP
- 6. Umgang mit Daten mit MVC mit AngularJS
- 7. Umgang mit binären Daten mit SOAP
- 8. Segmentierungsfehler beim Umgang mit Array von Struktur
- 9. Umgang mit Daten und Zeitzonen, mit Zend_Date
- 10. Umgang mit Zeilenumbrüchen in Daten mit Json.Net
- 11. Spring Daten Mongodb Umgang mit Daten mit @Query
- 12. Qt-Übersetzungen beim Umgang mit QUiloader
- 13. Best Practice beim Umgang mit Datenbank
- 14. mysql Syntaxfehler beim Umgang mit negativen Zahlen
- 15. Umgang mit veralteten Daten in REST?
- 16. "Unerwartetes Ende der Deklaration" beim Umgang mit 2D-Arrays
- 17. Umgang mit duplizierten Daten in SQL Server
- 18. SSAS Umgang mit nicht verknüpften Daten
- 19. Umgang mit fehlenden Daten in Pandas
- 20. Django Deployment: Umgang mit Daten in der Datenbank
- 21. Finding Prozess mit schweren Festplatte I/O
- 22. Pandas resample Umgang mit fehlenden Daten
- 23. Umgang mit NSError beim Lesen von Datei?
- 24. Parse-Fehler beim Umgang mit Strings
- 25. PyQt: Splash-Screen beim Laden von "schweren" Bibliotheken
- 26. Umgang mit Null Daten von DB zurückgegeben
- 27. Umgang mit fehlenden Daten in R
- 28. Umgang mit internationalen Daten in Python
- 29. auf meinen Eltern Controller Reaktion mit Lade
- 30. AFJSONRequestOperation Verzögerung in der Reaktion
Das war meine Hauptsorge. Ich war mir ziemlich sicher, dass ich keine Dinge wie control.Datasource = myData; im Hintergrund, aber es dauert einige Zeit zu vervollständigen. Daher war ich vor allem neugierig auf das Ausmaß der Arbeit, die ich rechtfertigen konnte, in den Hintergrund zu stellen. – ramnik