WinForms在处理“问题”时的UI响应能力;沉重的;数据
我正在修改windows窗体,以允许在后台加载数据,同时UI保持响应。数据的检索和绑定都需要相当长的时间。理想情况下,我会在后台同时做这两件事,但对于我应该在后台做什么样的UI更新(如在主线程之外)存在一些模糊性。一个在后台显示数据检索和数据绑定的可靠示例将非常有用。从服务器获取数据后,请不要从任何后台线程更新UI,并调用UI线程以更新UI绑定到的UI控件或数据集 在这种情况下,使用BackgroundWorker将有助于将事件连接起来 嗯WinForms在处理“问题”时的UI响应能力;沉重的;数据,winforms,user-interface,data-binding,multithreading,backgroundworker,Winforms,User Interface,Data Binding,Multithreading,Backgroundworker,我正在修改windows窗体,以允许在后台加载数据,同时UI保持响应。数据的检索和绑定都需要相当长的时间。理想情况下,我会在后台同时做这两件事,但对于我应该在后台做什么样的UI更新(如在主线程之外)存在一些模糊性。一个在后台显示数据检索和数据绑定的可靠示例将非常有用。从服务器获取数据后,请不要从任何后台线程更新UI,并调用UI线程以更新UI绑定到的UI控件或数据集 在这种情况下,使用BackgroundWorker将有助于将事件连接起来 嗯 Phil’检索可以也应该被推到后台线程——但有一些模式
Phil’检索可以也应该被推到后台线程——但有一些模式可以将其全部放在适当的位置 基本上,您将启动一个后台线程来检索数据,一旦完成,它将需要合并回UI线程以执行实际的UI更新(跨线程的UI更新是不好的) 有三种基本的后台线程方式供您探索
- 最简单/最有限(也是最古怪的IMO)的是BackgroundWorker组件
- 使用委托及其BeginInvoke()/EndInvoke()方法可以很好地平衡易用性和灵活性(并使用线程池线程)
- 使用原始线程对象提供的控制最多,但设置速度比线程池线程慢
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
阻塞
副标题()
无论您使用委托、后台工作人员还是任何其他协议,加载(如“从数据源检索”)可能都很简单。但绑定似乎很棘手,因为人们无法对其施加太多的控制,至少在大多数数据绑定控件中是如此——您可以异步检索数据,但一旦准备好,如何在后台将数据馈送到大型网格?这是你的问题吗?如果是,我想你可以:
- 创建(或子类化)视图控件,为异步加载提供接口李>
- 实现分页视图,一次只显示N条记录,这样在获取/格式化记录时UI不会被阻止
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