Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/user-interface/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
WinForms在处理“问题”时的UI响应能力;沉重的;数据_Winforms_User Interface_Data Binding_Multithreading_Backgroundworker - Fatal编程技术网

WinForms在处理“问题”时的UI响应能力;沉重的;数据

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’检索可以也应该被推到后台线程——但有一些模式

我正在修改windows窗体,以允许在后台加载数据,同时UI保持响应。数据的检索和绑定都需要相当长的时间。理想情况下,我会在后台同时做这两件事,但对于我应该在后台做什么样的UI更新(如在主线程之外)存在一些模糊性。一个在后台显示数据检索和数据绑定的可靠示例将非常有用。

从服务器获取数据后,请不要从任何后台线程更新UI,并调用UI线程以更新UI绑定到的UI控件或数据集

在这种情况下,使用BackgroundWorker将有助于将事件连接起来


Phil’

检索可以也应该被推到后台线程——但有一些模式可以将其全部放在适当的位置

基本上,您将启动一个后台线程来检索数据,一旦完成,它将需要合并回UI线程以执行实际的UI更新(跨线程的UI更新是不好的)

有三种基本的后台线程方式供您探索

  • 最简单/最有限(也是最古怪的IMO)的是BackgroundWorker组件
  • 使用委托及其BeginInvoke()/EndInvoke()方法可以很好地平衡易用性和灵活性(并使用线程池线程)
  • 使用原始线程对象提供的控制最多,但设置速度比线程池线程慢
我个人倾向于代表选项;一旦你确定了模式,他们就很容易合作了。后台工作人员在前面看起来不错,但有一些问题和管道缺失,这使得工作比你预期的更麻烦。让我简要介绍一下委托方法;我很快会更新

编辑

这里有一些代码,它是用VB编写的,但如果你是C#guy的话,应该很容易转录。关于背景线程的行为,您还有几个选项,因此这里有两个示例。非阻塞是我的首选,但如果您将其装配到现有代码中,那么阻塞可能会更容易

非阻塞,一旦后台线程完成,将在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
阻塞 副标题()

无论您使用委托、后台工作人员还是任何其他协议,加载(如“从数据源检索”)可能都很简单。但绑定似乎很棘手,因为人们无法对其施加太多的控制,至少在大多数数据绑定控件中是如此——您可以异步检索数据,但一旦准备好,如何在后台将数据馈送到大型网格?这是你的问题吗?如果是,我想你可以:

  • 创建(或子类化)视图控件,为异步加载提供接口
  • 实现分页视图,一次只显示N条记录,这样在获取/格式化记录时UI不会被阻止

这是我最关心的问题。我非常确定我不应该做像control.Datasource=myData;在后台,但它确实需要一些时间才能完成。所以我很好奇我能在多大程度上证明我可以把背景放进去。
    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