等待与 task.Result 相同的已完成任务? [英] Await on a completed task same as task.Result?

查看:34
本文介绍了等待与 task.Result 相同的已完成任务?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前正在阅读 Stephen Cleary 的C# 中的并发",我注意到了以下技术:

var completedTask = await Task.WhenAny(downloadTask, ti​​meoutTask);如果(完成任务 == 超时任务)返回空;返回等待下载任务;

downloadTask 是对 httpclient.GetStringAsync 的调用,而 timeoutTask 正在执行 Task.Delay.

如果没有超时,则downloadTask 已经完成.既然任务已经完成,为什么需要做第二次等待而不是返回 downloadTask.Result?

解决方案

这里已经有一些很好的答案/评论,但只是想插一句...

为什么我更喜欢 await 而不是 Result(或 Wait)有两个原因.首先是错误处理不同;await 不会将异常包装在 AggregateException 中.理想情况下,异步代码根本不必处理 AggregateException,除非它特别想要.

第二个原因更微妙一些.正如我在我的博客(和书中)所描述的那样,Result/Wait 可能导致死锁async 方法中使用时会导致更微妙的死锁.因此,当我阅读代码并看到 ResultWait 时,这是一个即时警告标志.Result/Wait 仅在您绝对确定任务已经完成时才是正确的.这不仅难以一目了然(在实际代码中),而且代码更改也更加脆弱.

这并不是说Result/Wait 应该永远被使用.我在自己的代码中遵循以下准则:

  1. 应用程序中的异步代码只能使用await.
  2. 异步实用程序代码(在库中)有时可以使用 Result/Wait 如果代码确实需要它.这种用法大概应该有注释.
  3. 并行任务代码可以使用ResultWait.

请注意,(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:

  1. Asynchronous code in an application can only use await.
  2. Asynchronous utility code (in a library) can occasionally use Result/Wait if the code really calls for it. Such usage should probably have comments.
  3. Parallel task code can use Result and Wait.

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆