从另一个线程更新UI [英] Updating UI from another thread

查看:109
本文介绍了从另一个线程更新UI的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



我们在一个应用程序上遇到问题,该应用程序正在TextBox的LostFocus上调用异步过程,然后异步过程需要能够在运行时更新主窗体UI(或从主窗体UI显示对话框).异步.

我们已经考虑过回调并使其具有真正的异步性,但是我们需要一切以正确的顺序执行,这适用于数据输入系统,其中数据输入的速度和准确性至关重要.

示例代码显示了我们正在尝试执行的操作,如果切换到BeginInvoke,则处理顺序不正确.

Hi,

We have an issue with an application where we are making a call to an asynchronous process on LostFocus of a TextBox, the asyncronous process then needs to be able to update the main form UI (or display a dialog from the main form UI) while running asynchronously.

We have thought about call backs and having it truely asynchronous but we need everything to execute in the correct order and this is for a data entry system where speed and accuracy of data entry is important.

Example code shows what we are trying to do and if you switch to BeginInvoke the order of processing is not correct.

<pre lang="vb">
Public Class Form1

    Private Sub TextBox1_LostFocus(ByVal sender As Object, ByVal e As System.EventArgs) Handles TextBox1.LostFocus

        '' execute the server subroutine
        Dim dlgt As New MethodInvoker(AddressOf Me.AsyncProcess)

        TextBox1.Text = "1"
        '' textbox should say 1

        '' call the server subroutine asynchronously, so the main thread is free
        Dim ar As IAsyncResult = dlgt.BeginInvoke(Nothing, Nothing)

        While ar.IsCompleted = False
            '' Application.DoEvents()
        End While
        '' textbox should now say 2

        TextBox1.Text = "3"
        '' textbox should now say 3
    End Sub

    Public Sub AsyncProcess()
        UpdateTextBox()
    End Sub

    Public Sub UpdateTextBox()
        If Me.InvokeRequired Then
            Me.Invoke(New MethodInvoker(AddressOf UpdateTextBox), "2")
        Else
            TextBox1.Text = "2"
        End If
    End Sub
End Class



有谁知道我们在忙于处理LostFocus事件时如何在主窗体线程上调用其他内容?

预先感谢.



Does anyone know how we can invoke something else on the main form thread while is is still busy processing the LostFocus event?

Thanks in advance.

推荐答案

附加说明.尽管Application.DoEvents()在这种情况下可以工作,但不是解决方案,因为它会错误地触发事件队列,并且高度不可靠.
Additional note to this. Although Application.DoEvents() will work in this scenario, it is NOT the solution as this fires off the event queue incorrectly and is highly unreliable.


您不能通过非调用任何与UI相关的内容-UI线程.相反,您需要使用System.Windows.Threading.DispatcherInvokeBeginInvoke方法(对于Forms或WPF)或System.Windows.Forms.Control(仅对于Forms).

在我过去的答案中,您将找到有关其工作原理的详细说明和代码示例:
Control.Invoke()与Control.BeginInvoke() [ ^ ],
Treeview Scanner和MD5的问题 [如何获取keydown事件在vb.net中的不同线程上操作 [启用禁用+多线程后控件事件不会触发 [ ^ ].

务必避免使用Application.DoEvents并使用线程本身,这一点非常重要.该调用仅阻塞调用代码,直到处理了应用程序事件队列中的所有事件.本质上,此代码将等待直到当前应用程序的事件队列为空.这是非常危险的,因为这可能永远不会发生,因为某些代码会生成其他事件,这是正常情况.有时,此调用用于在循环中通过按顺序逻辑将UI线程拆分为某些代码,并通过在循环中调用Application.DoEvents来保留应用程序的某种响应性. 从不这样做.通常,由于在依赖顺序的情况下无用地尝试更改事件处理的顺序,因此此类调用仍保留在代码中.

—SA
You cannot call anything related to UI from non-UI thread. Instead, you need to use the method Invoke or BeginInvoke of System.Windows.Threading.Dispatcher (for both Forms or WPF) or System.Windows.Forms.Control (Forms only).

You will find detailed explanation of how it works and code samples in my past answers:
Control.Invoke() vs. Control.BeginInvoke()[^],
Problem with Treeview Scanner And MD5[^].

See also more references on threading:
How to get a keydown event to operate on a different thread in vb.net[^],
Control events not firing after enable disable + multithreading[^].

It is very important to avoid Application.DoEvents by all means and use threads itself. This call simply blocks the calling code until all the events in the event queue of the application are handled. Essentially, this code makes waits until the event queue of current application is empty. This is very dangerous because this may never happen is some code generates additional events which is a normal situation. This call is sometimes used to split the UI thread into some code with sequential logic in a loop preserving some kind of responsiveness of the application by calling Application.DoEvents in a loop. Never do it. More often, such call remains in code as a result of useless attempts to change the order of event handling in case of dependency on such order.

—SA


这篇关于从另一个线程更新UI的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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