[英]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.