使用 Async 时如何中断和还原
本篇是 使用 Async 时如何汇报进度及取消任务 的狗尾续貂,演示了使用 async 时如何中断任务和如何在中断(或取消)任务后执行还原任务。
注:下面的用法只是个人的一点经验,如果你有更好的方案,欢迎一起讨论。
中断任务
外部中断通过 CancellationToken,就是之前提到的取消任务,此处不再复述。
内部中断参考 CancellationToken.ThrowIfCancellationRequested,通过抛出 OperationCanceledException:
var ex = new OperationCanceledException($"Interrupt: {reason}");
// 可以通过 Exception 的 Data 属性携带一些和中断任务相关的信息
ex.Data.Add("IsNeedCleanup", isNeedCleanup);
throw ex;
调用者依然通过捕获异常来处理中断:
try
{
int uploads = await UploadPicturesAsync(GenerateTestImages(), progressIndicator, _cts.Token);
}
catch (OperationCanceledException ex)
{
if (ex.Message.Contains("Interrupt:"))
{
isNeedCleanup = (bool)ex.Data["IsNeedCleanup"];
...
}
else ...
}
还原任务
为了保证异步任务无论是正常执行完毕还是中断(或取消)后还原任务都能执行,我们需要将还原任务放在 finally 块内部。
try
{
int uploads = await UploadPicturesAsync(GenerateTestImages(), progressIndicator, _cts.Token);
}
catch (OperationCanceledException ex)
{
if (ex.Message.Contains("Interrupt:"))
{
isNeedCleanup = (bool)ex.Data["IsNeedCleanup"];
...
}
else ...
}
finally
{
if (isNeedCleanup)
{
await CleanupAsync();
}
}