【发布时间】:2019-09-04 07:26:06
【问题描述】:
在我的应用程序中,我有一个按钮可以启动一个长时间运行的任务。为了不阻止 GUI,我在后台任务中执行此操作。按下按钮时执行以下函数:
private async void StartButtonHandler()
{
await Task.Run(() =>
{
FirstAction();
SecondAction();
ThirdAction();
});
}
现在我想让这个可以取消。我添加了第二个按钮并像这样修改了代码:
private CancellationTokenSource tokenSource;
private async void StartButtonHandler()
{
tokenSource?.Dispose();
tokenSource = new CanncellationTokenSource();
CancellationToken token = tokenSource.Token;
await Task.Run(() =>
{
FirstAction();
if(token.IsCancellationRequested)
{
return;
}
SecondAction();
if(token.IsCancellationRequested)
{
return;
}
ThirdAction();
});
}
private void CancelButtonHandler()
{
tokenSource.Cancel();
}
这很好用,但是当代码变长时会变得不舒服。想象一下,FirstAction() 函数再次调用了几个长时间运行的函数,我想在 FirstFunction() 中添加一个取消任务的地方。我必须像这样编写函数 FirstAction():
private void FirstAction(CancellationToken token)
{
FirstSubAction();
if(token.IsCancellationRequested)
{
return;
}
SecondSubAction();
if(token.IsCancellationRequested)
{
return;
}
ThirdSubAction();
if(token.IsCancellationRequested)
{
return;
}
FourthSubAction();
}
所以我的问题是:是否有一些模式可以帮助我使这段代码更清晰?在我看来,所有这些 if 语句都会分散真正发生的事情。
【问题讨论】:
-
这就是
CancellationToken.ThrowIfCancellationRequested()的用途。您可以从内部方法调用它并在外部级别处理OperationCanceledException。 -
您可以通过
token.ThrowIfCancellationRequested();尝试抛出异常,这在您想知道任务已完成还是未完成时很有用(在某个阶段被打断) -
我认为问题在于他想要某种方式将一大块代码包含在一个范围内,如果有人在
TaskCancellationSource上使用Cancel,任务将结束。不幸的是你不能@987654330 @ 来自外部的任务,您只能使用IsCancellationRequested和ThrowIfCancellationRequested从内部取消它们
标签: c# task cancellation