除了调用thread.Join()之外,如何等待线程完成运行? [英] How can I wait for a thread to finish running other than by calling thread.Join()?
问题描述
我正在一个项目中,该方法是从库中可用的应用程序中调用方法的。
I am working on a project where the methods are called from the an application which is available with the library.
我的按钮单击事件中包含以下代码:
I have the below code in my button click event:
Thread thread = new Thread(new ThreadStart(AddPics));
thread.Priority = ThreadPriority.Highest;
thread.Start();
execute();
但是在运行示例时,执行点始终移至执行位置。如何使程序首先执行 AddPics
方法。我已经尝试过 thread.Join()
并成功了,但是我想知道是否还有其他方法可以实现这一目标。
But while running the sample always the execution point moves to the execute. How to make the program to execute the AddPics
method first. I have tried thread.Join()
and it worked, but I want to know if there is any other way to achieve this.
推荐答案
您可以使用 Join
或 AutoResetEvent
等待添加图片线程修饰符,但是您不应该使用答案中稍后解释的任何一种方法。
You can use Join
or AutoResetEvent
to wait until add picture thread finishes, But you should not use either as explained later on the answer.
您可以通过使用<$获得相同的结果c $ c> AutoResetEvent 代替 Join
;它允许您设置阻止通知,因此请在调用 execute()
方法之前进行阻止,并且仅在 AddPics
时继续进行线程完成其工作:
You can achieve the same results by using AutoResetEvent
as alternative to Join
; it allows you to setup a blocking-notification, so block before calling the execute()
method and only proceed when AddPics
thread finishes its job:
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
表示该线程是后台线程,因此不会阻止应用程序终止。在此处中了解更多信息。
Note: Set IsBackground = true
to indicates that thread is a background thread so it will not prevent the application from terminating. read more about background thread here.
问题:
- 由于您使用的是单击按钮以运行该线程,则应添加某种机制以防止多次单击以多次运行该代码。
- 在调用<$时,您还将阻塞UI线程c $ c> Join()或
_finishAddPicsNotifier.WaitOne()
。
- Since you are using a button click to run the thread, you should add some mechanism to prevent multi-clicks at the same time to run the code multiple time.
- You are also blocking the UI thread when call
Join()
or_finishAddPicsNotifier.WaitOne()
.
要解决所有这些问题,一个好的设计是定义一个方法 OnFinishAddingPictures
,并在添加完图像后立即调用它,在此新方法调用 execute()
中,还应该从按钮单击中删除先前的 execute()
调用:
To fix all of that, a good design is to define a method OnFinishAddingPictures
and call it whenever finish adding images, inside this new method call execute()
, you should also remove the previous execute()
call from button click:
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
会立即执行。 - 始终记得检查
InvokeRequired
并使用control.Invoke(/*..*/)
每当通过不是UI线程的线程访问表单或控件方法和属性时。
- We get rid of the blocking using this mechanism.
- We are sure One and Only one call to the
AddPics
are executed at a moment. - Always remember to check
InvokeRequired
and usecontrol.Invoke(/*..*/)
whenever accessing form or control methods and properties from a thread that is not the UI thread.
这篇关于除了调用thread.Join()之外,如何等待线程完成运行?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!