RunWorkerAsync 在完成时关闭 BackgroundWorker

本文关键字:BackgroundWorker 完成时 RunWorkerAsync | 更新日期: 2023-09-27 18:34:22

我有一个后台工作者,需要根据选中的复选框数量多次调用 - 我写这个是为了获取复选框值并将它们放入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 的下一次迭代时,它崩溃了,表示工作线程很忙 - 即使工作线程已返回其 WorkerCompleted 状态。

如何确保线程在循环的下一次迭代之前关闭?

注意:我对包含!backgroundWorker1.IsBusy()的后台工作者有一个条件,但这(显然)只是跳过了剩余的迭代而没有执行。

RunWorkerAsync 在完成时关闭 BackgroundWorker

如果要按顺序处理每个项目,则没有理由为每个任务使用单独的后台工作者。因此,最好将foreach循环移动到DoWork方法中。但是,如果要处理 paralell 中的所有项目,则需要为每个项目创建一个后台工作线程。

您的 foreach 代码将立即触发所有元素的工作。这就是您获得异常的原因。

如果要按顺序启动工作线程,则只能在启动时调用一次 RunWorkerAsync,然后为每个 WorkerComplete-事件调用一次。但是,为什么不在工作代码中对每个进行处理呢?

后台工作者真的很忙,因为当第一次调用backgroundWorker1.RunWorkerAsync(rep);时,它不会等待任何东西,然后是第二个,第三个,...立即调用调用。

您应该在每次调用时创建 BackgroundWorker ,然后就可以了。

来自 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(直接或间接地,大多数并行操作将排队到池中)。

您可以使用 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);
                 });
相关文章:
  • 没有找到相关文章