如何取消正在运行的任务?

时间:2018-05-08 11:07:25

标签: c# task cancellation cancellationtokensource cancellation-token

我想取消正在运行的任务(当用户按下转义键时)。 当我点击“escape”键时,Form_KeyDown运行但不取消任务!

CancellationTokenSource tokenSource = new CancellationTokenSource();
CancellationToken token=new CancellationToken();

private async void Search_Button_ClickAsync(object sender, EventArgs e)
{
  token = tokenSource.Token;
  await (Task.Factory.StartNew(() =>
           {
             //...my program
           },
           token));

private void Form_KeyDown(object sender, KeyEventArgs e)
{
  if (e.KeyCode == Keys.Escape)
  {
    tokenSource.Cancel();
  }
}

1 个答案:

答案 0 :(得分:4)

除了你需要阻止代码在你的方法中运行之外,你做得很好。通过将取消令牌传递给Task.Factory.StartNew,您不会中止任务。 我引用Stephen Toub

  

将令牌传递到StartNew会将令牌与任务相关联。   这有两个主要好处:1)如果令牌已取消   在任务开始执行之前请求,任务不会被激活   执行。它不是立即过渡到Running,而是立即   过渡到已取消。这样可以避免运行任务的成本   无论如何它都会被取消。 2)如果身体的   任务还监视取消令牌并抛出一个   包含该令牌的OperationCanceledException(这是什么   ThrowIfCancellationRequested确实),然后当任务看到OCE时,   它检查OCE的令牌是否与任务的令牌匹配。如果它   是的,该例外被视为对合作的承认   取消和任务转换到已取消状态(相反   而不是故障状态。)

您需要手动检查您的令牌是否被取消并抛出操作取消异常,这些内容如下:

 private async void Search_Button_ClickAsync(object sender, EventArgs e)
    {
      cToken = cTokenSource.Token;
      await (Task.Factory.StartNew(() =>
               {

               for(int i=0;i<yourtaskcount;i++)
               { 
                 cToken.ThrowIfCancellationRequested();

                  //long work
               cToken));
    }
    private void Form_KeyDown(object sender, KeyEventArgs e)
    {
      if (e.KeyCode == Keys.Escape)
      {
        tokenSource.Cancel();
      }
    }