检索可以而且应该被推送到后台线程 - 但有一些模式可以将其全部到位。
基本上,您将启动一个后台线程来检索数据,一旦完成,它将需要合并回 UI 线程以执行实际的 UI 更新(跨线程的 UI 更新非常糟糕)。
后台线程的三种基本方式供您探索
- 最简单/最有限(并且在我看来很奇怪)的是BackgroundWorker组件
- 使用委托及其 BeginInvoke()/EndInvoke() 方法提供了易用性和灵活性的良好平衡(并使用 ThreadPool 线程)
- 使用原始 Thread 对象提供了最多的控制,但设置速度比 ThreadPool Threads 慢
就我个人而言,我倾向于“代表”选项;一旦你掌握了模式,它们就很容易使用。从前面看,BackgroundWorker 看起来不错,但有一些问题和缺失的管道,使其使用起来比您想象的更加麻烦。让我快速制作一个委托方法的简短示例;我会尽快更新...
edit
这里有一些代码,它是用 VB 编写的,但如果您是 C# 人员,应该很容易转录。关于后台线程的行为方式,您还有更多选择,因此这里有两个示例。非阻塞是我的首选,但如果您将其安装到现有代码中,那么阻塞可能对您来说更容易。
非阻塞,一旦后台线程完成,将在 UI 线程上调用回调方法 (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
Blocking子主函数()
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