[英]How to wait for a thread to finish its work
我有一个控制台应用程序。 一个类(例如,Worker)在单独的线程中执行某些工作,并在完成时引发事件。 但这永远不会发生,因为执行立即结束。 我如何等待线程完成并在引发事件后对其进行处理?
static void Main(string[] args)
{
Worker worker = new Worker();
worker.WorkCompleted += PostProcess;
worker.DoWork();
}
static void PostProcess(object sender, EventArgs e) { // Cannot see this happening }
编辑:更正了语句的顺序,但这不是问题。
您的比赛条件有限,因为您可以在报名参加比赛之前完成工作。 为了避免争用情况,请更改代码顺序,以便在开始工作之前注册事件,然后无论发生多快,都将始终引发该事件:
static void Main(string[] args)
{
Worker worker = new Worker();
worker.WorkCompleted += PostProcess;
worker.DoWork();
}
编辑:
好的,问题已被修改,因此您似乎真正要问的是如何等待PostProcess
完成执行。 有两种方法可以执行此操作,但是您必须添加更多代码。
最简单的方法是,因为事件总是在引发事件的同一线程上执行,所以在Worker
类创建的线程上调用Thread.Join
,例如,假定该线程公开为属性:
worker.Thread.Join();
(虽然说实话,我可能会保持Thread
私有,并在Worker
类上公开一个名为WaitForCompletion
之类的方法,以调用该方法)。
替代方法是:
在Worker
类中有一个WaitHandle
,可能是ManualResetEvent
,在完成所有工作时将其Set
为Set
,然后在其上调用WaitOne
。
在Worker
类中有一个volatile bool complete
字段,并在循环主体中使用Thread.Sleep
等待它设置为true
,然后循环(这可能不是一个好的解决方案,但可行)。
可能还有其他选择,但这是常见的选择。
您是否尝试过切换语句的顺序?
static void Main(string[] args)
{
Worker worker = new Worker();
worker.WorkCompleted += PostProcess;
worker.DoWork();
}
WorkCompleted是事件处理程序,必须预先设置。 工作分配不会调用此方法。WorkCompleted + = PostProcess;
Worker类应具有允许客户端等待线程完成的方法。 该方法将调用Thread.Join()
的适当重载以实现等待。 如果没有(您没有办法修改Worker
类),则它可能有一些方法可以访问内部Thread对象,您可以对该对象执行Join()。
如果两者都不具备,则需要查看(和/或在此处张贴) Worker
类接口的更多详细信息,以查看其是否具有适当的方法来等待完成。 如果没有它,那么您将需要自己的EventWaitHandle
对象, PostProcess()
事件处理程序可以在调用该对象时发出信号。
假设您无权访问Worker类,只需添加一个标志,该标志指示PostProcessing何时完成并进入睡眠状态,直到设置了该标志:
static bool isProcessed = false;
static void Main(string[] args)
{
Worker worker = new Worker();
worker.WorkCompleted += PostProcess;
worker.DoWork();
while(!isProcessed)
{
System.Threading.Thread.Sleep(-1);
}
}
static void PostProcess(object sender, EventArgs e)
{
// Cannot see this happening
isProcessed=true;
}
这应该可以解决问题,但是如果您不提供有关安装的更多信息,就无法保证它的强大功能。
您可以为此使用.net框架中的BackgroundWorker
类。
它正是您想要做的。 此外,它可以处理调用本身,因此您不会为此感到痛苦。
static void Main(string[] args)
{
BackgroundWorker worker = new BackgroundWorker();
worker.ProgressChanged += new ProgressChangedEventHandler(worker_ProgressChanged);
worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(worker_RunWorkerCompleted);
worker.WorkerReportsProgress = true;
worker.WorkerSupportsCancellation = false;
worker.DoWork += new DoWorkEventHandler(MyThreadMethod);
worker.RunWorkerAsync();
Console.Read();
}
static void MyThreadMethod(object sender, DoWorkEventArgs e)
{
Console.WriteLine("Worker starts working.");
for (int i = 1; i <= 100; i++)
{
((BackgroundWorker)sender).ReportProgress(i);
}
Console.WriteLine("Worker works fine.");
}
static void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
Console.WriteLine("Worker has finished.");
}
static void worker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
Console.WriteLine("Worker reports progress {0}", e.ProgressPercentage);
}
这听起来像是在工作线程中使用Begin / End异步模式的不错选择。 因此, Worker
包括开始异步执行工作的DoWork()
方法和在工作完成时触发的事件,还包括同步的Work()
方法(该方法返回Work()
结果)和BeginWork()
和可以用于异步使用的EndWork()
对。
有关此问题的更多信息,请参见http://msdn.microsoft.com/zh-cn/library/seta58yd(VS.71).aspx 。 可能适合您的情况吗?
我认为Application.Run初始化线程后。 然后在完成时调用Application.Exit
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.