簡體   English   中英

在異步無效中取消任務

[英]Cancel Task in async void

嗨,我有一個列表框 每當用戶選擇一個項目時,就會向網絡發送一個請求 現在我想在用戶選擇該項目時取消之前的操作,然后開始新的操作。

我使用以下代碼來做到這一點,我想知道這些代碼是否工作正常。 還是我應該嘗試另一種方式?

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

從技術上講,您可以這樣說,但是請注意:您觸發並忘記了,讓調用者返回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;
  }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM