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

ss2ws0br  于 2023-06-25  发布在  .NET
关注(0)|答案(1)|浏览(118)

我的团队中有一些人非常喜欢使用async 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是他们必须担心的事情,并且进程可能会因为没有捕获这些异常而崩溃(在前台或后台线程上)。
所以,我过于乐观的问题是:你认为哪种风格是每个人都应该使用的最好的风格,为什么?:)

vptzau2j

vptzau2j1#

在.Net框架本身中,当你传递一个CancellationToken作为参数时,你会得到一个TaskCanceledException。我不会反对这一点,创建自己的设计模式,因为熟悉.Net的人会熟悉你的代码。
我的指导方针是:取消令牌的块是应该处理TaskCanceledException的块,所以如果您出于自己的原因在方法中使用CancellationToken,请继续使用try-catch块。但是如果你获取token作为参数,让异常被抛出

相关问题