vb.net 使 UI 线程等待另一个线程完成
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/19246710/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Make UI thread wait until another thread is finished
提问by DanielH
I have some method run in the UI thread. Inside this method a new thread is created. I need UI thread waits until this new thread is finished because I want to wait for some results to be able to continue the method. But I don′t want to have UI frozen so meanwhile UI thread is waiting, it is also responding with UI.
我在 UI 线程中运行了一些方法。在此方法中创建了一个新线程。我需要 UI 线程等待这个新线程完成,因为我想等待一些结果才能继续该方法。但是我不想让 UI 被冻结,所以在 UI 线程等待的同时,它也在响应 UI。
Here is what I have now:
这是我现在所拥有的:
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
It seems that during WaitOnemethod UI thread sleeps and it doesn′t response so UI is frozen. Have you any idea where is the problem? Thank you guys.
似乎在WaitOne方法 UI 线程休眠期间它没有响应,因此 UI 被冻结。你知道问题出在哪里吗?谢谢你们。
EDITHere is a thing a forgot to write you: myThread creating is inside a for cycle. After myThread is finished, based on a results from myThread I have to decide If I should continue in the cycle (next loop) or exit cycle. My code is edited.
编辑这是一件忘记写给你的事情:myThread 创建是在 for 循环内。myThread 完成后,根据 myThread 的结果,我必须决定是继续循环(下一个循环)还是退出循环。我的代码已编辑。
If I use a BackgroundWorker, UI thread will automatically continue with next loop.
如果我使用 BackgroundWorker,UI 线程将自动继续下一个循环。
回答by Nikita
UI thread should not wait anything. It's a bad practice. Use Background Worker and attach apropriate listeners to events DoWork, ProgressChanged, RunWorkerCompleted http://msdn.microsoft.com/en-us/library/cc221403%28v=vs.95%29.aspx
UI 线程不应该等待任何东西。这是一个不好的做法。使用后台工作器并将适当的侦听器附加到事件 DoWork、ProgressChanged、RunWorkerCompleted http://msdn.microsoft.com/en-us/library/cc221403%28v=vs.95%29.aspx
回答by Carlos Landeras
If you use ThredSleep, or WaitOne. It will obviously freeze the screen because the main UI thread is stopped/waiting. I recommend you use Tasks and set a CallBack so the background job runs without freezing the UI. So can get the task result in a callback.
如果您使用ThredSleep, 或WaitOne. 它显然会冻结屏幕,因为主 UI 线程已停止/等待。我建议您使用 Tasks 并设置 CallBack,以便后台作业在不冻结 UI 的情况下运行。所以可以在回调中获取任务结果。
I give you an example:
我给你举个例子:
new TaskFactory().StartNew(BackGroundTask).ContinueWith(TaskCancelationCallBack);
//get the result in a callback
private void TaskCancelationCallBack(System.Threading.Tasks.Task task)
{
//Get Task Result
}
回答by Martin James
The UI is nearly always waiting, anyway - waiting for user input and other data. It's a state-machine, fed with messages via. an input queue. You should treat it as such, and provide thread-completion information as just another input message.
无论如何,UI 几乎总是在等待——等待用户输入和其他数据。它是一个状态机,通过它接收消息。一个输入队列。您应该这样对待它,并将线程完成信息作为另一个输入消息提供。
You should not try to expicitly wait in a GUI event-handler, no matter how tempting it may seem initially.
无论最初看起来多么诱人,您都不应该尝试在 GUI 事件处理程序中明确等待。
Look at Control.BeginInvoke() or Task class.
查看 Control.BeginInvoke() 或 Task 类。
回答by dbasnett
This pattern should do what you want
这种模式应该做你想做的
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

