异步取消任务

时间:2019-12-26 05:59:01

标签: c# task cancellation cancellationtokensource

您好,我有一个列表框每当用户选择一个项目时,就会将请求发送到网络。现在,我想取消当用户选择该项目然后开始新操作时。< / p>

我使用以下代码执行此操作,我想知道这些代码是否运行良好。还是我应该尝试另一种方式?

private CancellationTokenSource ts = new CancellationTokenSource();
private async void Subf2mCore(CancellationToken ct)
{
  HtmlDocument doc = await web.LoadFromWebAsync(url);
   ...
  foreach (var node in doc)
  {
    if (!ct.IsCancellationRequested)
    {
      ....
    }
  }
}

我以这种方式运行func

ts?.Cancel();
ts = new CancellationTokenSource();
Subf2mCore(ts.Token);

1 个答案:

答案 0 :(得分:6)

从技术上讲,您可以这样说,但要看:您丢掉了,让Task返回,以便呼叫者知道Subf2mCore是否已完成 失败已取消

private async Task Subf2mCore(CancellationToken ct)
{
  HtmlDocument doc = await web.LoadFromWebAsync(url);
   ...
  foreach (var node in doc)
  {
    // Often we cancel by throwing exception: 
    // it's easy to detect that the task is cancelled by catching this exception
    // ct.ThrowIfCancellationRequested();

    // You prefer to cancel manually: 
    // your cancellation can be silent (no exceptions) but it'll be 
    // difficult for caller to detect if task completed or not 
    // (partially completed and cancelled)
    if (!ct.IsCancellationRequested)
    {
      ....
    }
  }
}

// If we don't want to cancel 
private async Task Subf2mCore() => Subf2mCore(CancellationToken.None);

用法:不要忘记Dispose CancellationTokenSource实例:

using (CancellationTokenSource ts = new CancellationTokenSource()) {
  ...
  await Subf2mCore(ts.Token);
  ...
}

编辑::如果要从外部取消:

private CancellationTokenSource ts = null;

...

using (CancellationTokenSource _ts = new CancellationTokenSource()) {
  // previous task (if any) cancellation
  if (null != ts)
    ts.Cancel();

  // let cancel from outside
  ts = _ts;

  try {
    ...
    await Subf2mCore(_ts.Token);
    ...
  }
  finally {
    // task completed, we can't cancel it any more
    ts = null;
  }
}