C# 除了调用thread.Join()之外,我如何等待线程完成运行?
我正在从事一个项目,在这个项目中,这些方法是从库中提供的应用程序中调用的 我的按钮单击事件中有以下代码:C# 除了调用thread.Join()之外,我如何等待线程完成运行?,c#,multithreading,c#-3.0,C#,Multithreading,C# 3.0,我正在从事一个项目,在这个项目中,这些方法是从库中提供的应用程序中调用的 我的按钮单击事件中有以下代码: Thread thread = new Thread(new ThreadStart(AddPics)); thread.Priority = ThreadPriority.Highest; thread.Start(); execute(); 但是,在运行示例时,执行点总是移动到execute。如何使程序首先执行AddPics方法。我已经尝试了thread.Join(),它成功了,但我想
Thread thread = new Thread(new ThreadStart(AddPics));
thread.Priority = ThreadPriority.Highest;
thread.Start();
execute();
但是,在运行示例时,执行点总是移动到execute。如何使程序首先执行
AddPics
方法。我已经尝试了thread.Join()
,它成功了,但我想知道是否还有其他方法可以实现这一点。您可以使用Join
或AutoResetEvent
等待添加图片线程完成,但您不应该使用这两种方法,正如后面的答案所述。
您可以使用AutoResetEvent
作为Join
的替代方法来获得相同的结果;它允许您设置阻止通知,因此在调用execute()
方法之前阻止,并且仅当AddPics
线程完成其作业时才继续:
private AutoResetEvent _finishAddPicsNotifier = new AutoResetEvent(false);
private void OnMyButton_Click(object sender, EventArgs e)
{
//.....
new Thread(AddPics)
{
Priority = ThreadPriority.Highest,
IsBackground = true, //will explain later
}.Start();
_finishAddPicsNotifier.WaitOne();//this will block until receive a signal to proceed
execute();//this method will only be called after the AddPics method finished
/.....
}
private void AddPics()
{
try{
//.......
}
finally{
_finishAddPicsNotifier.Set();//when finished adding the pictures, allow the waiting method to proceed
}
}
注意:设置IsBackground=true
表示线程是后台线程,因此不会阻止应用程序终止。阅读更多关于后台线程的信息
问题:
- 由于您使用的是单击按钮来运行线程,因此应该添加一些机制来防止同时多次单击以多次运行代码
- 调用
或Join()
时,也会阻塞UI线程\u finishadpicsniffer.WaitOne()
OnFinishAddingPictures
并在完成添加图像时调用它,在这个新方法调用execute()
,您还应该从按钮单击中删除以前的execute()
调用:
private readonly object _oneAddPicturesLocker = new object();
private void OnMyButton_Click(object sender, EventArgs e)
{
//.....
new Thread(AddPics)
{
Priority = ThreadPriority.Highest,
IsBackground = true,
}.Start();
}
private void AddPics()
{
if (Monitor.TryEnter(_oneAddPicturesLocker))
{
//we only can proceed if no other AddPics are running.
try
{
//.....
OnFinishAddingPictures();
}
finally
{
Monitor.Exit(_oneAddPicturesLocker);
}
}
}
private void OnFinishAddingPictures()
{
execute();
}
注意:
- 我们使用这种机制消除了阻塞
- 我们确信一次只能执行一个对
的调用AddPics
- 无论何时从不是UI线程的线程访问表单或控件方法和属性,请始终记住选中
并使用invokererequired
control.Invoke(/*..*/)
AddPics
的线程时拥有响应式UI?如果是,那么您可以对WinForms使用以下构造:
while (thread.IsAlive)
System.Windows.Forms.Application.DoEvents();
如果要暂停直到线程完成,为什么不直接调用
AddPics
-为什么要使用线程?能否告诉我们为什么不使用线程。Join()?这可能有助于明确您的意图,并将产生更好的答案。使用Application.DoEvents
是个坏主意,它产生的问题比解决的问题多。调用“DoEvents()”只能在复杂的应用程序中导致问题。但是,如果某个人有头脑,那么“做的事”可以起到善的作用,而不是恶的作用:)它总是坏的,因为你把它写在那里,并伪造它。一个例子是你的程序和每件事都很好,6个月后,一个新的场景即将出现,你希望在计算机时间改变时得到通知“例如”你通过收听windows消息轮询来做到这一点。。运行应用程序并对其进行测试,一切都很好。。但是等一下,我们忘记了应用程序。DoEvents()
,它隐藏在代码中的某个地方,因此如果在应用程序运行时收到消息,您的应用程序将不会收到通知。DoEvent()
“6个月后…”==“复杂应用程序”@Lokesh:您尝试过这种方法吗,它是否满足您的需要?