1

我在 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 被冻结期间。你知道问题出在哪里吗?感谢你们。

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

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

4

4 回答 4

2

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

于 2013-10-08T12:26:26.083 回答
0

这种模式应该做你想做的

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
于 2013-10-08T12:58:41.620 回答
0

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

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

查看 Control.BeginInvoke() 或 Task 类。

于 2013-10-08T12:08:21.133 回答
0

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

我给你举个例子:

 new TaskFactory().StartNew(BackGroundTask).ContinueWith(TaskCancelationCallBack);  

//get the result in a callback

private void TaskCancelationCallBack(System.Threading.Tasks.Task task)
{

     //Get Task Result
} 
于 2013-10-08T12:06:15.907 回答