简体   繁体   English

.NET C#:HttpClient 和 TaskCanceledException 异常

[英].NET C# : HttpClient and the TaskCanceledException exception

I've started using System.Net.Http.HttpClient and it's a great class.我已经开始使用System.Net.Http.HttpClient ,这是一个很棒的课程。 I'm at a point where I want to give my program's user the ability to cancel operations, for example if a bunch of HTTP requests take too long to complete.我现在想让我的程序用户能够取消操作,例如,如果一堆 HTTP 请求需要很长时间才能完成。 So, naturally, I've come across the CancellationTokenSource class and modified my calls to the async methods of HttpClient to also pass them a CancellationToken .因此,很自然地,我遇到了CancellationTokenSource类并修改了我对 HttpClient 的异步方法的调用,以将CancellationToken传递给它们。 In my UI code I can now "cancel that token", and indeed it interrupts whatever HTTP request was in progress at that point.在我的 UI 代码中,我现在可以“取消该令牌”,并且实际上它会中断当时正在进行的任何 HTTP 请求。

What I didn't expect, however, is that this causes the interrupted method to throw the TaskCanceledException exception.然而,我没想到的是,这会导致被中断的方法抛出TaskCanceledException异常。

Here's my question : I've looked at the MSDN documentation for HttpClient and I have found no mention of that exception.这是我的问题:我查看了HttpClient的 MSDN 文档,但没有发现提及该异常。 I suppose that is because it's a common behavior to any async method that takes a CancellationToken , but so far I haven't found much information about that.我想这是因为它是任何采用CancellationToken 的异步方法的常见行为,但到目前为止我还没有找到太多关于它的信息。 Can you confirm or infirm my supposition, and point me to the relevant documentation ?你能证实或否定我的假设,并指出相关文件吗?

My "real question" is whether I'm using the CancellationToken mechanism right, meaning, is that exception supposed to happen, or am I doing something wrong ?我的“真正的问题”是我是否正确地使用了CancellationToken机制,意思是异常应该发生,还是我做错了什么?

If that exception is supposed to happen, and if it is a mechanism I can rely on, then it will simplify my code.如果该异常应该发生,并且它是我可以依赖的机制,那么它将简化我的代码。 Right now, I test my token's IsCancellationRequested property after each call to HttpClient async methods to determine if my methods should proceed or return, but with this exception, all that additional code becomes pointless.现在,我在每次调用HttpClient异步方法后测试我的令牌的IsCancellationRequested属性,以确定我的方法是应该继续还是返回,但除了这个例外,所有额外的代码都变得毫无意义。

I'm cancelling the token using this statement :我正在使用以下语句取消令牌:

myCancellationTokenSource.Cancel();

Is catching TaskCanceledException and checking Task.Canceled a good idea? 捕获 TaskCanceledException 并检查 Task.Canceled 是个好主意吗?

In the .Net framework itself when you pass a CancellationToken as a parameter you will get back a TaskCanceledException .在 .Net 框架本身中,当您将CancellationToken作为参数传递时,您将返回TaskCanceledException I would not go against that and create my own design pattern because people who are familiar with .Net will be familiar with your code.我不会反对并创建我自己的设计模式,因为熟悉 .Net 的人会熟悉您的代码。

My guideline is this: The one that cancels the token is the one that should handle the TaskCanceledException , so If you're using a CancellationToken inside your method for your own reasons, go ahead and use a try-catch block.我的指导方针是:取消令牌的那个是应该处理TaskCanceledException那个,所以如果您出于自己的原因在方法中使用CancellationToken ,请继续使用try-catch块。 But if you get the token as a parameter, let the exception be thrown .但是,如果您将令牌作为参数,则抛出异常

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

Don't throw OperationCanceledException after you've completed the work, just because the token was signaled.不要在完成工作后抛出 OperationCanceledException,仅仅因为令牌已发出信号。 Return a successful result and let the caller decide what to do next.返回一个成功的结果,让调用者决定下一步做什么。 The caller can't assume you're cancellable at a given point anyway so they have to be prepared for a successful result even upon cancellation.呼叫者无论如何都不能假设您可以在给定点取消,因此即使取消,他们也必须为成功的结果做好准备。

In my opinion, cancellationToken.ThrowIfCancellationRequested() is the easiest way to handle most interactions with the cancellationToken.在我看来, cancellationToken.ThrowIfCancellationRequested()是处理与 cancelToken 的大多数交互的最简单方法。 Then you only need to handle the exception.那么你只需要处理异常。

Throwing TaskCanceledException when canceled is the norm for all methods which accept a CancellationToken parameter.取消时抛出TaskCanceledException是所有接受CancellationToken参数的方法的规范。 That this isn't always documented is (IMO) an oversight.这并不总是记录在案是(IMO)疏忽。

But at least there are a few docs for the overall pattern, to document the behavior in a general sense:但至少有一些关于整体模式的文档,以记录一般意义上的行为:

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

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

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

Documents also sometimes just mention OperationCanceledException to imply TaskCanceledException , since they are super- and sub-class.文档有时也只是提到OperationCanceledException来暗示TaskCanceledException ,因为它们是超类和子类。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM