等待与 task.Result 相同的已完成任务? [英] Await on a completed task same as task.Result?
问题描述
我目前正在阅读 Stephen Cleary 的C# 中的并发",我注意到了以下技术:
var completedTask = await Task.WhenAny(downloadTask, timeoutTask);如果(完成任务 == 超时任务)返回空;返回等待下载任务;
downloadTask
是对 httpclient.GetStringAsync
的调用,而 timeoutTask
正在执行 Task.Delay
.>
如果没有超时,则downloadTask
已经完成.既然任务已经完成,为什么需要做第二次等待而不是返回 downloadTask.Result
?
这里已经有一些很好的答案/评论,但只是想插一句...
为什么我更喜欢 await
而不是 Result
(或 Wait
)有两个原因.首先是错误处理不同;await
不会将异常包装在 AggregateException
中.理想情况下,异步代码根本不必处理 AggregateException
,除非它特别想要.
第二个原因更微妙一些.正如我在我的博客(和书中)所描述的那样,Result
/Wait
可能导致死锁 和 在 async
方法中使用时会导致更微妙的死锁.因此,当我阅读代码并看到 Result
或 Wait
时,这是一个即时警告标志.Result
/Wait
仅在您绝对确定任务已经完成时才是正确的.这不仅难以一目了然(在实际代码中),而且代码更改也更加脆弱.
这并不是说Result
/Wait
应该永远被使用.我在自己的代码中遵循以下准则:
- 应用程序中的异步代码只能使用
await
. - 异步实用程序代码(在库中)有时可以使用
Result
/Wait
如果代码确实需要它.这种用法大概应该有注释. - 并行任务代码可以使用
Result
和Wait
.
请注意,(1) 是目前最常见的情况,因此我倾向于在任何地方使用 await
并将其他情况视为一般规则的例外.
I'm currently reading "Concurrency in C# Cookbook" by Stephen Cleary, and I noticed the following technique:
var completedTask = await Task.WhenAny(downloadTask, timeoutTask);
if (completedTask == timeoutTask)
return null;
return await downloadTask;
downloadTask
is a call to httpclient.GetStringAsync
, and timeoutTask
is executing Task.Delay
.
In the event that it didn't timeout, then downloadTask
is already completed. Why is necessary to do a second await instead of returning downloadTask.Result
, given that the task is already completed?
There are already some good answers/comments here, but just to chime in...
There are two reasons why I prefer await
over Result
(or Wait
). The first is that the error handling is different; await
does not wrap the exception in an AggregateException
. Ideally, asynchronous code should never have to deal with AggregateException
at all, unless it specifically wants to.
The second reason is a little more subtle. As I describe on my blog (and in the book), Result
/Wait
can cause deadlocks, and can cause even more subtle deadlocks when used in an async
method. So, when I'm reading through code and I see a Result
or Wait
, that's an immediate warning flag. The Result
/Wait
is only correct if you're absolutely sure that the task is already completed. Not only is this hard to see at a glance (in real-world code), but it's also more brittle to code changes.
That's not to say that Result
/Wait
should never be used. I follow these guidelines in my own code:
- Asynchronous code in an application can only use
await
. - Asynchronous utility code (in a library) can occasionally use
Result
/Wait
if the code really calls for it. Such usage should probably have comments. - Parallel task code can use
Result
andWait
.
Note that (1) is by far the common case, hence my tendency to use await
everywhere and treat the other cases as exceptions to the general rule.
这篇关于等待与 task.Result 相同的已完成任务?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!