0

I have simple wpf application with one button and one textblock. Button click event handler run next code:

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

And this doesn't work (it hangout) until I use await

var result = await ebClient.DownloadStringTaskAsync("http://google.com");
textBlock.Text = result;

But in simple console application it work fine.

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

Can you explane me why first variant doesn't work in wpf?

sepulka
  • 405
  • 4
  • 15

2 Answers2

7

This is a commonly seen issue with sync-contexts; basically, the .Result can't get the sync-context until the UI thread is available, and the UI thread will not be available until .Result completes (or fails). Basically, you have deadlocked yourself, which is why you shouldn't use .Wait() or .Result unless you know the sync-context is safe - just await.

It works in a console app because there is no sync-context: the continuation can be marked complete on a pool thread. In WPF, the sync-context pushes work to the UI thread, which is can't do because of the deadlock.

A hacky fix would be to add .ConfigureAwait(false) after the *Async method:

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

But this works for all the wrong reasons and should be avoided. Either use await, or use a synchronous call. Don't do "sync over async" - it is a very bad idea.

Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
0

It looks like you're deadlocking on the UI event thread. The accepted answer on the question below explains it in more detail:

Deadlock while blocking async HttpClient call within a task continuation

Community
  • 1
  • 1
Dan Hermann
  • 1,107
  • 1
  • 13
  • 27