5

Modyfikuję formularz okna, aby umożliwić ładowanie danych w tle, gdy interfejs użytkownika pozostaje aktywny. Dane zabierają zauważalny czas na odzyskanie i powiązanie. Idealnie byłoby zrobić oba w tle, ale jest pewna niejasność odnośnie tego, jakiego rodzaju aktualizacje interfejsu użytkownika powinienem robić w tle (tak jak poza głównym wątkiem). Solidny przykład pokazujący pobieranie danych i powiązanie danych w tle byłby bardzo pomocny.Szybkość reakcji interfejsu użytkownika WinForms podczas pracy z "ciężkimi" danymi

Odpowiedz

6

Odzyskanie mogą i powinny zostać zepchnięty do wątku tła - ale jest pewne wzorce, aby umieścić to wszystko na swoim miejscu.

Zasadniczo uruchomi się wątek tła, aby pobrać dane, po zakończeniu będzie musiał ponownie połączyć się z wątkiem interfejsu użytkownika, aby wykonać aktualne aktualizacje interfejsu użytkownika (aktualizacje interfejsu użytkownika w wątkach są bardzo źle złe).

Są trzy podstawowe sposoby tle gwintów do odkrywania

  • najprostszym/najbardziej ograniczona (i ekscentryczny IMO) jest składnikiem BackgroundWorker
  • użyciu delegatów oraz ich BeginInvoke()/EndInvoke() metody Zapewniamy miłą równowagę łatwość i elastyczność (i używać puli wątków wątki)
  • stosując surowe obiektów wątku zapewnia największą kontrolę, ale są wolniejsze niż w konfiguracji puli wątków wątków

Osobiście pochylam się w stronę opcji Delegatów; są bardzo łatwe w obsłudze, gdy tylko otrzymasz wzór. BackgroundWorker wydaje się być dobry z przodu, ale ma kilka problemów i brakujące instalacje, które sprawiają, że praca jest bardziej uciążliwa niż można się spodziewać. Pozwól mi pobudzić krótką próbę podejścia Delegata; Będę aktualizować wkrótce ...

edit

Oto niektóre kodu, to w VB ale powinien być na tyle łatwe do transkrypcji jeśli jesteś facet C#. Masz kilka dodatkowych opcji dotyczących zachowania wątku tła, więc tutaj są dwie próbki. Niezablokowanie jest moim preferowanym rozwiązaniem, ale jeśli dopasujesz go do istniejącego kodu, zablokowanie może być łatwiejsze.

non-blocking, metoda zwrotna (GetData_Complete) zostanie wywołana w wątku UI, gdy wątek tła jest kompletna

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 

Blokowanie 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 
1

Nie aktualizuj interfejsu użytkownika z żadnego wątku w tle, gdy pobierzesz dane z serwera, wywołaj z powrotem do wątku interfejsu użytkownika, aby zaktualizować formanty interfejsu użytkownika lub zestaw danych, do którego jest powiązany twój interfejs użytkownika.

Korzystanie z usługi BackgroundWorker pomoże w tym przypadku po prostu połączyć zdarzenia.

HTH

Phil”

+0

To była moja główna troska. Byłem całkiem pewien, że nie powinienem robić takich rzeczy jak control.Datasource = myData; w tle, ale ukończenie zajmuje trochę czasu. Byłem więc w większości ciekawy, jaki zakres pracy mógłbym uzasadnić w tle. – ramnik

0

Ładowanie (jak w "pobieranie ze źródła danych") może być trywialne, bez względu na to, czy używasz delegatów, pracowników pracujących w tle czy jakiegokolwiek innego protokołu.Ale wiązanie wydaje się trudne, ponieważ nie ma zbytniej kontroli nad nim, przynajmniej w większości kontrolek związanych z danymi - możesz pobierać dane asynchronicznie, ale gdy już masz gotowe, jak je wprowadzić do dużej siatki w tle? Czy to twoje pytanie? Jeśli tak, myślę, że możesz:

  • utworzyć (lub podklasę) kontrolę widoku, zapewniając interfejsy dla obciążenia asynchronicznego;
  • Zaimplementuj widok stronicowany, wyświetlając tylko N rekordów naraz, aby interfejs użytkownika nie był blokowany podczas pobierania/formatowania rekordów.
Powiązane problemy