现在我们有了“ await”关键字,使用ContinueWith方法有什么好处?

时间:2019-10-04 06:28:13

标签: c#

拍摄以下代码:

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;

如果我错了,请纠正我,但是我相信,从性能角度来看,两个代码最终都完成了相同的工作量。

1 个答案:

答案 0 :(得分:3)

第二个片段没有任何好处,在分配另一个任务对象时不会“节省”任何线程,并且通过将所有异常包装在AggregateException中来使调试和异常处理变得更加困难。

任务是承诺,某些东西会在未来中产生一些输出。可能是这样的:

  • 在线程池线程上运行的后台操作
  • 不是在任何线程上运行的网络/ IO操作,而是等待网络/ IO驱动程序发出信号,表明IO已完成。
  • 在间隔后发出任务信号的计时器。这里没有任何执行方式。
  • 一个TaskCompletionSource,在一段时间后会发出信号。这里也没有执行

HttpClient.GetAsyncHttpClient.GetStringAsyncContent.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);