簡體   English   中英

RunWorkerAsync在完成時關閉BackgroundWorker

[英]RunWorkerAsync close BackgroundWorker on complete

我有一個后台工作程序,需要根據選中的復選框數多次調用它-我已編寫了此背景程序以獲取復選框值並將其放入List

List repSelected = new List();

填充它,然后像下面這樣迭代:

foreach (string rep in repSelected)
{
    backgroundWorker1.RunWorkerAsync(rep);
    backgroundWorker1.RunWorkerCompleted += new RunWorkerCompletedEventHandler(backgroundWorker1_RunWorkerCompleted);
}

異步DoWork代碼如下所示:

BackgroundWorker worker = sender as BackgroundWorker;
string rep = e.Argument.ToString();

if (worker.CancellationPending == true)
{
    e.Cancel = true;
}
else
{
    DirectoryExists(rep);
    ProcessRunner(rep); //Rars some large files - expensive
}

然后,該進程運行WorkerComplete,問題是當該進程返回以進行Worker的下一次迭代時,它崩潰了,說出該Worker處於忙碌狀態-即使該Worker返回了其WorkerCompleted狀態。

如何確保在下一次循環迭代之前關閉線程?

注意:我對包含!backgroundWorker1.IsBusy()的后台工作器有條件,但是(顯然)這只是跳過了其余的迭代而沒有執行。

如果要按順序處理每個項目,則沒有理由為每個任務使用單獨的后台工作人員。 因此,最好將foreach循環移至DoWork方法中。 但是,如果要處理paralell中的所有項目,則需要為每個項目創建一個后台工作程序。

從MSDN:

如果后台操作已經在運行,則再次調用RunWorkerAsync將引發InvalidOperationException。

因此,您不能使用BackgroundWorker來維護任務隊列 (並且按順序推送所有任務,而無需等待一個任務完成)。 您對此有不同的解決方案,例如,如果要繼續使用BackgroundWorker ,則可以這樣做:

backgroundWorker1.RunWorkerAsync(repSelected);

然后像下面這樣更改您的DoWork方法:

BackgroundWorker worker = sender as BackgroundWorker;

foreach (string rep in (IEnumerable<string>)e.Argument)
{
    if (worker.CancellationPending == true)
    {
        e.Cancel = true;
        return;
    }
    else
    {
        DirectoryExists(rep);
        ProcessRunner(rep); //Rars some large files - expensive
    }
}

作為替代方案,您可以考慮更改執行此任務的方式,例如,使用System.Threading.Tasks.TaskThreadPool (直接或間接將大多數並行操作排隊到池中)。

您的foreach代碼將立即觸發所有元素的工作。 這就是為什么您會得到例外。

如果要順序啟動工作程序,則只能在啟動時調用RunWorkerAsync一次,然后再為每個WorkerComplete事件調用一次。 但是,為什么不在工作者代碼中進行foreach的處理呢?

BackgroundWorker確實很忙,因為當第一次調用backgroundWorker1.RunWorkerAsync(rep); ,它不等待任何內容,因此第二,第三,...調用立即被調用。

您應該在每次調用時創建BackgroundWorker,這樣就可以了。

您可以雇用parallel.foreach和多個背景工作人員;

Parallel.ForEach(YourListofStrings,
                 (q) =>
                 {
                     BackgroundWorker worker = new BackgroundWorker();
                     worker.DoWork += new DoWorkEventHandler(worker_DoWork);
                     worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(worker_RunWorkerCompleted);
                     worker.RunWorkerAsync(q);
                 });

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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