等待任务结果时会发生什么? [英] What happens while waiting on a Task's Result?

查看:29
本文介绍了等待任务结果时会发生什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用 HttpClient 将数据发布到 .NET 4.0 项目中的远程服务.我不关心这个操作阻塞,所以我想我可以跳过 ContinueWith 或 async/await 并使用 Result.

在调试时,我遇到了远程服务器没有响应的问题.当我逐步浏览代码时,我的代码似乎只是停止在第三行运行……当前堆栈指针行不再以黄色突出显示,并且没有前进到下一行.它只是消失了.我花了一段时间才意识到我应该等待请求超时.

var client = new HttpClient();var task = client.PostAsync("http://someservice/", someContent);var response = task.Result;

我的理解是在 Task 上调用 Result 会导致代码同步执行,表现得更像这样(我知道 HttpClient 中没有 Post 方法):

var client = new HttpClient();var response = client.Post("http://someservice/", someContent);

我不确定这是件坏事,我只是想弄清楚.由于 HttpClient 返回的是 Tasks 而不是直接返回结果,我的应用程序是否会自动利用异步,即使我认为我正在避免它?

解决方案

在 Windows 中,所有 I/O 都是异步的.同步 API 只是一种方便的抽象.

因此,当您使用 HttpWebRequest.GetResponse 时,实际发生的是 I/O 启动(异步),调用线程(同步)阻塞,等待它完成.

同样,当您使用 HttpClient.PostAsync(..).Result 时,I/O 启动(异步),调用线程(同步)阻塞,等待它完成.

我通常建议人们使用 await 而不是 Task.ResultTask.Wait ,原因如下:

  1. 如果您在 async 方法的结果上阻塞了 Task,您可以很容易陷入僵局.
  2. Task.ResultTask.Wait 将任何异常包装在 AggregateException 中(因为这些 API 是来自 TPL 的保留).因此错误处理更加复杂.

但是,如果您了解这些限制,在某些情况下,阻止 Task 可能会很有用(例如,在控制台应用程序的 Main 中).

I'm using the HttpClient to post data to a remote service in a .NET 4.0 project. I'm not concerned with this operation blocking, so I figured I could skip ContinueWith or async/await and use Result.

While debugging, I ran into an issue where the remote server wasn't responsive. As I stepped through the code, it seemed like my code just stopped running on the third line... the current stack pointer line stopped being highlighted yellow, and didn't advance to the next line. It just disappeared. It took me a while to realize that I should wait for the request to timeout.

var client = new HttpClient();
var task = client.PostAsync("http://someservice/", someContent);
var response = task.Result;

My understanding was that calling Result on the Task caused the code to execute synchronously, to behave more like this (I know there is no Post method in the HttpClient):

var client = new HttpClient();
var response = client.Post("http://someservice/", someContent);

I'm not sure this is a bad thing, I'm just trying to get my head around it. Is it really true that by virtue of the fact that the HttpClient is returning Tasks instead of the results directly, my application is automatically taking advantage of asynchrony even when I think I'm avoiding it?

解决方案

In Windows, all I/O is asynchronous. Synchronous APIs are just a convenient abstraction.

So, when you use HttpWebRequest.GetResponse, what actually happens is the I/O is started (asynchronously), and the calling thread (synchronously) blocks, waiting for it to complete.

Similarly, when you use HttpClient.PostAsync(..).Result, the I/O is started (asynchronously), and the calling thread (synchronously) blocks, waiting for it to complete.

I usually recommend people use await rather than Task.Result or Task.Wait for the following reasons:

  1. If you block on a Task that is the result of an async method, you can easily get into a deadlock situation.
  2. Task.Result and Task.Wait wrap any exceptions in an AggregateException (because those APIs are holdovers from the TPL). So error handling is more complex.

However, if you're aware of these limitations, there are some situations where blocking on a Task can be useful (e.g., in a Console application's Main).

这篇关于等待任务结果时会发生什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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