c# - 现在我们有了“await”关键字,使用 ContinueWith 方法有什么好处吗?
问题描述
图片如下代码:
var client = new HttpClient();
var response = await client.GetAsync("www.someaddress.yo");
string content = await response.Content.ReadAsStringAsync();
通过以下方式编写上述代码,除了可能节省单个线程之外,是否还有其他好处:
var client = new HttpClient();
string content = await client.GetAsync("www.someaddress.yo")
.ContinueWith(r => r.Result.Content.ReadAsStringAsync()).Result;
如果我错了,请纠正我,但我相信在性能方面,两个代码最终都会做同样多的工作。
解决方案
第二个片段没有任何好处,在分配另一个任务对象时不会“保存”任何线程,并且通过将任何异常包装在 AggregateException 中来使调试和异常处理更加困难。
任务是对某事将在未来产生一些输出的承诺。那可能是:
- 在线程池线程上运行的后台操作
- 不在任何线程上运行的网络/IO 操作,而是等待网络/IO 驱动程序发出 IO 已完成的信号。
- 一个计时器,它在间隔后发出任务信号。这里没有执行。
- 一段时间后收到信号的 TaskCompletionSource。这里也没有执行
HttpClient.GetAsync
,HttpClient.GetStringAsync
或者Content.ReadAsStringAsync
都是这样的IO操作。
await
不会使任何东西异步运行。它只等待已经执行的任务完成而不阻塞。
ContinueWith
使用第二个片段的方式没有任何收获。此代码只是分配另一个任务来包装由ReadAsStringAsync
. .Result
返回原始任务。
如果该方法失败,.Result
将抛出一个AggregateException
包含原始异常的异常 - 或者它是一个包含 AggregateException 的 AggregateException 包含原始异常?我不想知道。还不如用过Unwrap()
。最后,一切还在等待。
唯一的区别是第一个片段在每次等待之后返回到原始同步上下文中。在桌面应用程序中,这将是 UI。在许多情况下,您希望这样做 - 这允许您使用响应更新 UI,而无需任何类型的编组。你可以写
var response = await client.GetAsync("www.someaddress.yo");
string content = await response.Content.ReadAsStringAsync();
textBox1.Text=content;
在其他情况下,您可能不希望这样,例如库编写者不希望库影响客户端应用程序。这就是ConfigureAwait(false)
进来的地方:
var response = await client.GetAsync("www.someaddress.yo").ConfigureAwait(false);
string content = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
推荐阅读
- javascript - 检测何时停止拖动块
- php - 在 WooCommerce 中显示基于自定义表的自定义字段值
- powerapps - 如果具有多个条件的函数没有返回正确的值
- python - 数据框有一个值列和唯一 ID 的列表,没有
- r - 在我的 R 包中提供 S4 方法
- android - Android中的自动滚动文本视图
- android - 将 BuildConfig.FLAVOR 与 android 数据绑定一起使用
- r - 如何在 R ggplot 循环中显示具有 2 种视觉效果的标题
- c# - ReferenceEquals 的快速 Equals 用于深度不可变的 C# 9 记录?
- javascript - 如何在 react-native 中从数组中删除多个对象