WebClient.DownloadStringTaskAsync 没有等待就无法工作

WebClient.DownloadStringTaskAsync doesn't work without await

我有一个带有一个按钮和一个文本块的简单 wpf 应用程序。按钮单击事件处理程序 运行 下一个代码:

var resultTask = webClient.DownloadStringTaskAsync("http://google.com");
textBlock.Text = resultTask.Result;

在我使用 await

之前这不起作用(它是环聊)
var result = await ebClient.DownloadStringTaskAsync("http://google.com");
textBlock.Text = result;

但在简单的控制台应用程序中它工作正常。

var resultTask = webClient.DownloadStringTaskAsync("http://google.com");
Console.WriteLine(resultTask.Result);

你能解释一下为什么第一个变体在 wpf 中不起作用吗?

您似乎在 UI 事件线程上陷入僵局。以下问题的公认答案对其进行了更详细的解释:

这是同步上下文的常见问题;基本上,.Result 在 UI 线程可用之前无法获取同步上下文,并且 UI 线程在 .Result 完成(或失败)之前不可用.基本上,你自己陷入了僵局,这就是为什么你不应该使用 .Wait().Result 除非你知道同步上下文是安全的 - 只是 await.

它在控制台应用程序中工作,因为没有同步上下文:可以在池线程上将延续标记为完成。在 WPF 中,同步上下文将工作推送到 UI 线程,由于死锁,这是无法做到的。

一个 hacky 修复是在 *Async 方法之后添加 .ConfigureAwait(false)

var resultTask = webClient.DownloadStringTaskAsync("http://google.com")
    .ConfigureAwait(false); 

但这出于所有错误的原因而起作用,应该避免。要么使用 await,要么使用同步调用。不要这样做 "sync over async" - 这是一个非常糟糕的主意。