我有一个简单的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中不起作用吗?
答案 0 :(得分:7)
这是sync-contexts常见的问题;基本上,.Result
在UI线程可用之前无法获取同步上下文,并且在.Result
完成(或失败)之前UI线程将不可用。基本上,您已经陷入僵局,这就是为什么您不应该使用.Wait()
或.Result
,除非您知道同步上下文是安全的 - 只需await
。
它在控制台应用程序中工作,因为没有同步上下文:可以在池线程上标记完成继续。在WPF中,sync-context将工作推送到UI线程,由于死锁而无法做到这一点。
一个hacky修复方法是在.ConfigureAwait(false)
方法之后添加*Async
:
var resultTask = webClient.DownloadStringTaskAsync("http://google.com")
.ConfigureAwait(false);
但是这可以解决所有错误的原因,应该避免。使用await
或使用同步调用。不要“同步异步” - 这是一个非常糟糕的主意。
答案 1 :(得分:0)
看起来你在UI事件线程上遇到了死锁。以下问题的接受答案更详细地解释了它:
Deadlock while blocking async HttpClient call within a task continuation