WinForms处理“重”的UI响应数据 [英] WinForms UI responsiveness when dealing with "heavy" data

查看:311
本文介绍了WinForms处理“重”的UI响应数据的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在修改Windows窗体,以允许在UI保持响应时在后台加载数据。数据需要明显的时间来检索和绑定。理想情况下,我会在后台做这两个,但是在后台应该做什么样的UI更新(如主线程外)有一些歧义。一个在后台显示数据检索和数据绑定的实例非常有用。

I'm modifying a windows form to allow data to be loaded in the background while the UI remains responsive. The data takes noticeable time to both retrieve and bind. Ideally, I would do both in the background, but there is some ambiguity about what kind of UI updates I should be doing in the background (as in outside the main thread). A solid example that shows data retrieval and data binding in the background would be very helpful.

推荐答案

被推送到后台线程 - 但是有一些模式可以将其全部放在原位。

The retrieval can, and should, be pushed off to a background thread--but there's some patterns to put it all in place.

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

Basically you'll start a background thread to retrieve the data, once it's done it will need to merge back into the UI thread to do the actual UI updates (UI updates across threads are bad bad bad).

有三种基本的背景线程为您探索

There's three basic ways of background threading for you to explore


  • 最简单/最有限(和古怪的IMO)是BackgroundWorker组件


  • 使用原始的Thread对象提供最多的控制,但是较慢设置比ThreadPool线程

个人我瘦向上选择代表选项;一旦你的模式下降,他们就很容易工作。 BackgroundWorker看起来很好,但是有一些问题和缺失的管道,使得工作比您预期的更麻烦。让我举一个简短的代表方法样本;我稍后会更新...

Personally I lean towards the Delegates option; they're pretty easy to work with once you get the pattern down. The BackgroundWorker seems nice up front but has some gotchas and missing plumbing that make it more cumbersome to work with than you'd expect. Let me whip up a short sample of the Delegate approach; I'll update shortly...

编辑

这是一些代码,它在VB中,但如果您是C#人,应该很容易转录。您还有几个关于您希望后台线程行为的选项,因此这里有两个示例。非阻塞是我的首选,但如果您将其适用于现有代码,则阻止可能会更容易。

Here's some code, it's in VB but should be easy enough to transcribe if you're a C# guy. You have a couple more options on how you want the background thread to behave, so there's two samples here. Non-blocking is my prefered, but if you're fitting it into existing code then blocking might be easier for you.

非阻塞,回调方法(GetData_Complete)将在后台线程完成后在UI线程上调用

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()

Blocking 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

这篇关于WinForms处理“重”的UI响应数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆