我如何知道取消的异步任务是不是完成?
Posted
技术标签:
【中文标题】我如何知道取消的异步任务是不是完成?【英文标题】:How do I know if a cancelled async task is finished?我如何知道取消的异步任务是否完成? 【发布时间】:2021-03-29 06:50:07 【问题描述】:最后在cmets后加
我有一个运行时间相当长的 Windows 窗体。所以我想我会让它异步。
因为有时操作者不想等到它完成,所以我给机会取消任务:
private CancellationTokenSource = new CancellationTokenSource();
private async Task<TResult> DoLongProcessingAsync(CancellationToken token)
// do some long async processing; allow cancelling
await Task.Delay(TimeSpan.FromSeconds(30), token);
return new TResult() ...;
public async void ButtonStart_Clicked(object sender, ...)
this.buttonStart.Enabled = false;
this.ShowBusy(true);
await this.DoLongProcessing(this.cancellationTokenSource.Token);
this.ShowBusy(false);
this.buttonStart.Enabled = true;
现在假设操作员在 DoLongProcessingAsync 完成之前关闭了表单。
private async void OnFormClosing(object sender, ...)
bool closingAlloged = this.AskOperatorIfClosingAllowed();
if (closingAllowed)
this.cancellationTokenSource.Cancel();
// TODO: await until DoLongProcessingAsync is finished
如何等待 LongProcessing 完成?
加法
有人说我应该等待任务。但是很可惜,Task 是 ButtonStart_Clicked 中的一个局部变量。我不确定是否应该将其作为类内的字段。
直到现在我还没有计划它,但只要它是一个局部变量,我可以通过单击几次来启动多个任务,并通过取消 CancellationTokenSource 将它们全部取消。
或者这真的是禁忌吗?
【问题讨论】:
如果你想知道任务何时完成,那么你await
它,就像你在其他想知道操作何时完成的方法中所做的那样。
await
它并将其包装到一个 try-catch 中,如果等待的方法在内部调用传递的令牌上的 ThrowIfCancellationRequested
方法,您预计会出现 OperationCanceledException
。
我认为这可能很有趣:***.com/questions/16656523/….
Related: .NET Async in shutdown methods? 如果你能确保取消会立即发生,那就简单多了,这样你就可以Wait
同步挂起的任务而不是await
ing它。跨度>
取消会在一秒左右结束,所以取消不会有问题。我想我必须让我的任务成为一个字段,并确保只有一个任务在运行。感觉很尴尬,任务仍然存在,即使它完成了。
【参考方案1】:
您已经在 (a) 等待 ButtonStart_Clicked
方法中的任务。
取消一个Task后,在OnFormClosing
里面,可以catch一个TaskCanceledException
:
public async void ButtonStart_Clicked(object sender, ...)
this.buttonStart.Enabled = false;
this.ShowBusy(true);
try
await this.DoLongProcessing(this.cancellationTokenSource.Token);
catch (TaskCanceledException ex)
// handle task cancelled here
catch (Exception ex)
//handle other exceptions here
finally
this.ShowBusy(false);
this.buttonStart.Enabled = true;
【讨论】:
但我在 OnFormClosing 中。我怎么知道 ButtonStart_Clicked 已经完成?我当然可以等待 SemaphoreSlim,但没有更聪明的方法吗?以上是关于我如何知道取消的异步任务是不是完成?的主要内容,如果未能解决你的问题,请参考以下文章