.NET C#: HttpClient和TaskCanceledException异常

3
我开始使用System.Net.Http.HttpClient类,这是一个很好的类。现在我想让我的程序用户有能力取消操作,例如如果一堆HTTP请求需要太长时间才能完成。因此,我自然而然地遇到了CancellationTokenSource类,并修改了对HttpClient异步方法的调用,以便向它们传递CancellationToken。在我的UI代码中,我现在可以“取消该令牌”,并且确实会打断正在进行的任何HTTP请求。
然而,我没有预料到的是,这会导致被打断的方法抛出TaskCanceledException异常。
我的问题是:我查看了HttpClient的MSDN文档,没有提到这个异常。我认为这是因为这是任何接受CancellationToken的异步方法的常见行为,但到目前为止,我没有找到太多关于它的信息。您能否确认或否定我的假设,并指向相关文档?
我的“真正的问题”是,我是否正确使用了CancellationToken机制,也就是说,这个异常是否应该发生,还是我做错了什么?
如果这个异常应该发生,并且它是我可以依赖的机制,那么它将简化我的代码。现在,我在每次调用HttpClient异步方法后测试我的令牌的IsCancellationRequested属性,以确定我的方法是否应该继续执行或返回,但是有了这个异常,所有额外的代码都变得无意义了。
我使用以下语句取消令牌:
myCancellationTokenSource.Cancel();

1
当你询问“我是否正在正确地做这件事”时,请使用代码而不是用语言来解释你当前正在做什么。代码跨越所有语言障碍。 - Scott Chamberlain
它的意思是抛出一个异常。 - ProgrammingLlama
Scott,我同意你的观点,但我并没有做什么特别的事情(无意冒犯)。我会看看我能做些什么。 - Jean Roch
约翰:这是我相信的,但我想要100%的确定性,因此我请求提供文档。我不能仅仅基于某人在SO上告诉我“它应该这样做”来做出软件设计决策,我相信你能理解。 - Jean Roch
在我看来,如果假定的行为引发异常,那真的很愚蠢。完全不合逻辑。 - The incredible Jan
2个回答

1
当取消时,抛出TaskCanceledException是所有接受CancellationToken参数的方法的常规做法。没有始终记录这一点是一个疏忽(在我看来)。
但至少有一些文档概述了该模式,以便以一般方式记录行为:

https://learn.microsoft.com/en-us/dotnet/standard/threading/cancellation-in-managed-threads

https://learn.microsoft.com/en-us/dotnet/standard/parallel-programming/task-cancellation

https://learn.microsoft.com/en-us/dotnet/standard/parallel-programming/how-to-cancel-a-task-and-its-children

有时候文档只是提到OperationCanceledException,暗示这个异常是TaskCanceledException的超类或子类。


1

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

在.Net框架本身中,当您将CancellationToken作为参数传递时,您将收到TaskCanceledException。我不会违背这一点并创建自己的设计模式,因为熟悉.Net的人们将熟悉您的代码。

我的指导方针是:取消令牌的人应该处理TaskCanceledException,因此如果您在方法中使用CancellationToken以满足自己的需求,请使用try-catch块。但是,如果您将令牌作为参数获取,则让异常抛出。

https://blogs.msdn.microsoft.com/andrewarnottms/2014/03/19/recommended-patterns-for-cancellationtoken/

不要在完成工作后抛出OperationCanceledException异常,仅因为标记被触发。返回成功的结果,让调用者决定下一步该做什么。调用者不能假设在给定点上你是可取消的,因此即使取消也必须准备好处理成功的结果。
在我看来,cancellationToken.ThrowIfCancellationRequested()是处理大多数与cancellationToken交互的最简单方法。然后只需要处理异常。

我认为我们在同一页面上。您是否有任何关于HttpClient相关的TaskCancelledException的MSDN链接? - Jean Roch
我不确定他们是否记录他们认为是标准的东西...但你总可以通过源代码挖掘。例如:https://github.com/dotnet/corefx/blob/6b9440735abc9c4e369376bca097766527971a7a/src/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/ConnectionCloseReadStream.cs#L21 - Alex AIT

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接