从另一个线程更新UI

时间:2011-12-14 02:37:45

标签: vb.net multithreading user-interface

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

我们已经考虑过回调并使其真正异步,但我们需要以正确的顺序执行所有操作,这适用于数据录入系统,其中数据输入的速度和准确性非常重要。

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

公共类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

结束班

有人知道我们如何在主表单线程上调用其他东西,而仍在忙着处理LostFocus事件吗?

提前致谢。

2 个答案:

答案 0 :(得分:2)

查看BackgroundWorker课程。您可以使用此类在后台执行长时间运行的任务,并通过事件将状态报告回UI。该类支持“ProgressChanged”事件和“RunWorkerCompleted”事件。我在下面列出了一些示例代码,以展示如何使用它来完成您正在尝试的操作。

Imports System.ComponentModel
Imports System.Threading

Public Class Form1

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

        TextBox1.Text = "1"

        ' Execute the long-running task in the background
        BackgroundWorker1.RunWorkerAsync()

    End Sub

    Private Sub BackgroundWorker1_DoWork(ByVal sender As Object, 
        ByVal e As DoWorkEventArgs) Handles BackgroundWorker1.DoWork

        ' Do your heavy lifting in this method; report progress as needed by 
        ' calling ReportProgress, which will in turn call Progress_Changed
        ' safely on the UI thread.  (DO NOT update the UI directly from here.)

        Dim worker As BackgroundWorker = CType(sender, BackgroundWorker)

        ' Simulate processing for a second
        Thread.Sleep(1000)

        ' Report progress to the UI (the first arg is the percentage complete;
        ' the secong arg can be a string or any object)
        worker.ReportProgress(50, "2")

        ' Simulate processing for another second
        Thread.Sleep(1000)

    End Sub

    Private Sub BackgroundWorker1_ProgressChanged(ByVal sender As Object, 
        ByVal e As ProgressChangedEventArgs) 
        Handles BackgroundWorker1.ProgressChanged

        ' Update the UI with progress from the background task
        TextBox1.Text = CType(e.UserState, String)

    End Sub

    Private Sub BackgroundWorker1_RunWorkerCompleted(ByVal sender As Object,
        ByVal e As RunWorkerCompletedEventArgs) 
        Handles BackgroundWorker1.RunWorkerCompleted

        ' Update the UI when the background task is finished
        TextBox1.Text = "3"

    End Sub
End Class

答案 1 :(得分:0)

我认为你最好的选择是不要试图等待方法同步完成。将异步调用后要实现的LostFocus处理程序方法的其余部分更改为回调并将其传递给BeginInvoke。这允许UI线程在维持操作顺序的同时保持响应。