如何在 C# Optimal 中使用多种方法取消后台工作者?

How to cancel a backgroundworker with multiple methods in c# optimal?

我有一个 backgroundworker,它有几个不同的函数和循环。 我在互联网上找到的每个示例都只有一个循环和一个函数。 现在我想知道是否存在通过按钮取消工作人员的简短解决方案。 我只知道两个我认为不是最优的解决方案。

1: 在每个 function/loop -> 长而混乱的代码中添加一个 if/else

loop
{          
      if (worker.CancellationPending == true)
      {
          e.Cancel = true;
          break;
      }
      else
      {
          do calculation
      }
}

2:像这里一样用 abort 杀死后台线程 (How to “kill” background worker completely?)

我希望计算在按下取消按钮后立即停止,无论此时执行哪个循环或函数。 有没有比我更好的机会?

编辑:我不知道为什么 How can I cancel a Task without LOOP 应该解决我的问题,因为我 有很多不同的循环

与后台工作者一起工作时,您唯一的选择就是在代码中添加检查以查看操作是否已被取消。

如何实现这完全取决于您,但我想说您想在每个可能耗时的操作开始时进行检查,例如数据库查询或文件系统操作,并且肯定在每个循环的开始。

现在,正如您已经注意到的那样,当您涉及多个方法时,它会变得更加棘手。在这种情况下,将您的工作人员存储在 class 级别的字段中可能是合适的,这样您就可以在任何适用的情况下从每个方法中简单地检查其取消状态。

一种有用的方法是利用您自己的自定义异常 class。您可以将代码包装在 try-catch 块中的顶级方法中,然后每当您发现后台工作程序已在调用堆栈中更深的某个地方被取消时,您可以只抛出一个异常实例,该实例将是由 catch 块处理。

这是我编写的一个简单示例。

class CancellationException : Exception
{
    public object State { get; private set; }

    public CancellationException(object state)
    {
        this.State = state;
    }
}

private void DoSomething()
{
    if (_worker.CancellationPending)
    {
        throw new CancellationException("cancelled from blah blah");
    }
}

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
    try
    {
        DoSomething();
    }
    catch (CancellationException ce)
    {
        e.Cancel = true;
    }
}

请注意,异常中的 State 属性 可用于确定取消命中在您的进程中的哪个位置,以便您可以清理资源等。