Извлечение может и должно быть перенесено в фоновый поток - но есть некоторые шаблоны, чтобы поместить все это на место.
По сути, вы запускаете фоновый поток для извлечения данных, как только это будет сделано, потребуется выполнить слияние обратно с потоком пользовательского интерфейса, чтобы выполнить фактические обновления пользовательского интерфейса (обновления пользовательского интерфейса между потоками - это плохо, плохо, плохо).
Существует три основных способа создания фоновых потоков для изучения
- самый простой / наиболее ограниченный (и причудливый IMO) компонент BackgroundWorker
- использование делегатов и их методов BeginInvoke () / EndInvoke () обеспечивают хороший баланс простоты и гибкости (и используют потоки ThreadPool)
- использование необработанных объектов Thread обеспечивает максимальный контроль, но его настройка медленнее, чем ThreadPool Threads
Лично я склоняюсь к варианту «Делегаты»; с ними довольно легко работать, как только вы сломаете шаблон. BackgroundWorker выглядит неплохо, но в нем есть некоторые ошибки и недостающая сантехника, которые делают работу с ней более громоздкой, чем вы ожидаете. Позвольте мне привести краткий пример подхода делегата; Я скоро обновлю ...
редактировать
Вот некоторый код, он написан на VB, но должен быть достаточно легким для расшифровки, если вы парень на C #. У вас есть еще пара опций о том, как вы хотите, чтобы фоновый поток вел себя, поэтому здесь есть два примера. Я предпочитаю не блокировать, но если вы встраиваете его в существующий код, блокирование может быть проще для вас.
Неблокируемый метод обратного вызова (GetData_Complete) будет вызываться в потоке пользовательского интерфейса после завершения фонового потока
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
Блокировка
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