在异步Void中取消任务

7

你好,我有一个列表框。每当用户选择一个项目时,就会向Web发送请求。现在我想在用户选择项目并开始新操作时取消以前的操作。

我使用了以下代码来实现这一点。我想知道这些代码是否可以很好地工作。还是我应该尝试另一种方式?

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)
    {
      ....
    }
  }
}

我是这样运行函数的

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

是的,您可以取消 Subf2mCore 的执行,但要让其他人(即 Subf2mCore 的调用者)知道:将其放置为 private async Task Subf2mCore(CancellationToken ct) {...} - Dmitry Bychenko
1个回答

5

从技术角度来说,你可以这样做,但是请注意:你“发射并忘记”,让返回的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);

使用方式:不要忘记DisposeCancellationTokenSource实例:

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;
  }
}

谢谢,现在我使用的是这样的方式 ts?.Cancel(); using (ts = new CancellationTokenSource()) { await Subf2mCore(ts.Token); },但是我遇到了这个错误 System.ObjectDisposedException: 'The CancellationTokenSource has been disposed.' - user11453013
@Git:我已经编辑了答案,我们应该取消本地的 CancellationTokenSource - Dmitry Bychenko
谢谢,但我在这一行遇到了错误“_ts = CancellationTokenSource()”,不能像方法一样使用。 - user11453013
@git:抱歉打错字了,我漏掉了 new - Dmitry Bychenko

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接