代码之家  ›  专栏  ›  技术社区  ›  DanielH

使UI线程等待另一个线程完成

  •  1
  • DanielH  · 技术社区  · 11 年前

    我在UI线程中运行了一些方法。在这个方法中创建了一个新的线程。我需要UI线程等待,直到这个新线程完成,因为我想等待一些结果才能继续该方法。但我不想冻结UI,所以在UI线程等待的同时,它也在用UI进行响应。

    以下是我现在拥有的:

    Dim _WaitHandler As New System.Threading.AutoResetEvent(False)
    
    Public Sub Method()
    
       For i As Integer = 0 To 100
    
          Dim myThread As Thread = New Thread(AddressOf ThreadMethod)
          myThread.Start()
    
          _WaitHandler.WaitOne()
    
          //next loop or exit?
       Next
    
       //this code I want to process after myThread is finished
       //but also I don´t want to freeze UI during WaitOne method
    
    End Sub
    
    Private Sub ThreadMethod()
    
       //do something...
       _WaitHandler.Set()
    
    End Sub
    

    似乎在 WaitOne 方法UI线程休眠,它没有响应,因此UI被冻结。你知道问题出在哪里吗?谢谢你们。

    编辑 有一件事是a忘记给你写的:myThread创建是在for循环中。myThread完成后,根据myThread的结果,我必须决定是继续循环(下一个循环)还是退出循环。我的代码已编辑。

    若我使用BackgroundWorker,UI线程将自动继续下一个循环。

    4 回复  |  直到 11 年前
        1
  •  2
  •   Nikita    11 年前

    UI线程不应该等待任何东西。这是一种糟糕的做法。 使用后台工作程序并将适当的侦听器附加到事件DoWork、ProgressChanged和RunWorkerCompleted http://msdn.microsoft.com/en-us/library/cc221403%28v=vs.95%29.aspx

        2
  •  0
  •   Carlos Landeras Yuriy Galanter    11 年前

    如果您使用 ThredSleep WaitOne 。它显然会冻结屏幕,因为主UI线程已停止/正在等待。我建议您使用Tasks并设置CallBack,以便后台作业在不冻结UI的情况下运行。因此可以在回调中获得任务结果。

    我给你举个例子:

     new TaskFactory().StartNew(BackGroundTask).ContinueWith(TaskCancelationCallBack);  
    
    //get the result in a callback
    
    private void TaskCancelationCallBack(System.Threading.Tasks.Task task)
    {
    
         //Get Task Result
    } 
    
        3
  •  0
  •   Martin James    11 年前

    无论如何,UI几乎总是在等待——等待用户输入和其他数据。这是一台状态机,通过发送消息。输入队列。您应该这样对待它,并将线程完成信息作为另一个输入消息来提供。

    您不应该试图在GUI事件处理程序中进行显式等待,无论最初看起来多么诱人。

    查看Control.BeginInvoke()或Task类。

        4
  •  0
  •   dbasnett    11 年前

    这个模式应该符合您的要求

    Public Sub Method()
        Dim myThread As Threading.Thread = New Threading.Thread(AddressOf ThreadMethod)
        myThread.IsBackground = True
        myThread.Start()
    End Sub
    
    Private Sub ThreadMethod()
        'do something...
        AfterThreadMethod()
    End Sub
    
    Delegate Sub AfterThreadMethodDel()
    Private Sub AfterThreadMethod()
        '   //this code I want to process after myThread is finished
        'if this code must run on the UI then
        If Me.InvokeRequired Then
            'not on the UI
            Dim foo As New AfterThreadMethodDel(AddressOf AfterThreadMethod)
            Me.Invoke(foo)
        Else
            'on the UI
        End If
    End Sub