如何在c#optimal中使用多种方法取消后台工作人员?

如何在c#optimal中使用多种方法取消后台工作人员?,c#,multithreading,visual-studio,backgroundworker,C#,Multithreading,Visual Studio,Backgroundworker,我有一个具有一些不同函数和循环的后台工作人员。 我在网上找到的每个例子都只有一个循环和一个函数。 现在,我想知道是否存在一个简短的解决方案,用一个按钮取消工人。 我只知道两个我认为不是最优的解决方案 1:在每个函数/循环->长而混乱的代码中添加if/else loop { if (worker.CancellationPending == true) { e.Cancel = true; break;

我有一个具有一些不同函数和循环的后台工作人员。 我在网上找到的每个例子都只有一个循环和一个函数。 现在,我想知道是否存在一个简短的解决方案,用一个按钮取消工人。 我只知道两个我认为不是最优的解决方案

1:在每个函数/循环->长而混乱的代码中添加if/else

loop
{          
      if (worker.CancellationPending == true)
      {
          e.Cancel = true;
          break;
      }
      else
      {
          do calculation
      }
}
2:使用如下所示的中止来终止backgroundworker线程()

我希望在点击cancel按钮后立即停止计算,无论此时执行哪个循环或函数。 还有比我更好的机会吗


编辑:我不知道为什么要解决我的问题,因为我有许多不同的循环。

当与后台工作人员一起工作时,实际上唯一的选择是在代码中添加检查,以查看操作是否已取消

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

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

一种有用的方法是利用您自己的自定义异常类。您可以将代码封装在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;
    }
}

请注意,异常中的
状态
属性可用于确定取消操作在流程中的位置,以便您可以清理资源等。

当与后台工作人员一起工作时,实际上您唯一的选择是在代码中添加检查以查看操作是否已取消

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

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

一种有用的方法是利用您自己的自定义异常类。您可以将代码封装在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
属性可用于确定取消在您的流程中的位置,以便您可以清理资源等。

可能重复的可能重复的可能重复的,嗯,是的,使用自定义异常类是一个好主意。在那里,我也可以处理所有其他的优点。谢谢。如果您将
任务
库与
取消令牌
一起使用,则有一个
throwifcancellationrequest
方法封装此模式。嗯,是的,使用自定义异常类是一个好主意。在那里,我也可以处理所有其他的优点。谢谢。如果将
任务
库与
取消令牌
s一起使用,则有一个
throwifcancellationrequest
方法封装此模式。