簡體   English   中英

如何等待線程完成工作

[英]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之類的方法,以調用該方法)。

替代方法是:

  1. Worker類中有一個WaitHandle ,可能是ManualResetEvent ,在完成所有工作時將其SetSet ,然后在其上調用WaitOne

  2. Worker類中有一個volatile bool complete字段,並在循環主體中使用Thread.Sleep等待它設置為true ,然后循環(這可能不是一個好的解決方案,但可行)。

可能還有其他選擇,但這是常見的選擇。

您是否嘗試過切換語句的順序?

static void Main(string[] args)
{
    Worker worker = new Worker();
    worker.WorkCompleted += PostProcess;
    worker.DoWork();
}

WorkCompleted是事件處理程序,必須預先設置。 工作分配不會調用此方法。WorkCompleted + = PostProcess;

使用WaitHandle類成員(WaitOne,WaitAny或WaitAll)

在MSDN中查看詳細信息

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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM