捕获TaskCanceledException并检查Task.Canceled是个好主意?

时间:2014-07-03 16:55:42

标签: c# .net task-parallel-library task cancellation-token

我的团队中有些人真的喜欢使用异步Task进行编码。有时他们喜欢使用CancellationToken参数。

我不确定的是团队是否应该使用这种代码(A):

async Task<someObject> DoStuff(CancellationToken t)
{
    while (!t.IsCanceled)
    {
        try {
            Task.Delay(5000, t);
        }
        catch (AggregateException e) // or is it TaskCanceledException or OperationCanceledException? I don't know? :)
        {
        }
        // poll something, return someObject, or null
    }
    return null;
}

这显然意味着调用者可能必须自己检查取消令牌以确定是否继续处理,并且他们可能必须处理null retVals:

var retVal = await DoStuff(token);
if (token.IsCanceled) { ... }

但是,如果我们采用依赖于TaskCanceledException的第二种代码(B):

async Task<someObject> DoStuff(CancellationToken t)
{
    while(true)
    {
        Task.Delay(5000, t);
        // poll something, return someObject, or null
    }
}

实现代码肯定更简单 - 调用者可以选择是否处理异常,但是我不禁担心调用者可能忘记 TaskCanceledException是什么东西他们不得不担心,由于他们没有捕获这些异常(在前台或后台线程上),进程可能会崩溃。

所以,我过于乐观的措辞是:你认为每个 :)

1 个答案:

答案 0 :(得分:28)

在.Net框架中,当您传递CancellationToken作为参数时,您将获得TaskCanceledException。我不会反对并创建我自己的设计模式,因为熟悉.Net的人会熟悉你的代码。

我的指导原则是:取消令牌的那个是应该处理TaskCanceledException的令牌,所以如果您出于自己的原因在方法中使用CancellationToken,请转到提前并使用try-catch块。 但是如果您将令牌作为参数获取,则抛出异常