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

PEY*_*MAN 2 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();
  }
}
Run Code Online (Sandbox Code Playgroud)

Mis*_*tyK 7

除了需要停止代码在方法内运行之外,您一切正常。通过将取消令牌传递给 Task.Factory.StartNew,您不会中止任务。让我引用Stephen Toub

将令牌传递到 StartNew 会将令牌与任务相关联。这有两个主要好处:1) 如果令牌在 Task 开始执行之前请求取消,则 Task 将不会执行。它不会转换为 Running,而是立即转换为 Canceled。这避免了运行任务的成本,如果它无论如何都会在运行时被取消。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();
      }
    }
Run Code Online (Sandbox Code Playgroud)