2

is it okay when UI is freezed for 5 seconds, when a button is clicked at first time? I mean when I click the button to load content from website, then I cannot move the window for 5 seconds.

My code looks like this:

private async void Button_Click(object sender, RoutedEventArgs e)
{            
    var html = await GetHtmlAsync("http://msdn.microsoft.com"); 
    MessageBox.Show(html.Substring(0, 10));
}


public async Task<string> GetHtmlAsync(string url)
{
    var webClient = new WebClient();
    return await webClient.DownloadStringTaskAsync(url);
}

However, if I click the above button the second time or click other async buttons, then there is no UI freezing.

So is it okay when UI is freezed for 5 seconds, when a button is clicked at first time?

StepUp
  • 36,391
  • 15
  • 88
  • 148
  • Be more precise. It is ok for the results to be delayed, not for the UI to freeze. How do you establish that it is frozen? – H H Jun 10 '18 at 14:43
  • Try to change the `async` call to `var html = await Task.Run(AsyncFoo);` ? – Fabjan Jun 10 '18 at 14:43
  • @HenkHolterman I mean when I click the button to load content from website, then I cannot move the window for 5 seconds. – StepUp Jun 10 '18 at 14:48
  • @Fabjan yeah, if I use `var html = await Task.Run(AsyncFoo);` then there is no UI freezing. Is it possible to achieve the same result without using `Task.Run()`? – StepUp Jun 10 '18 at 14:52
  • It shouldn't happen - make sure this is an mcve. That means, create a scrap project with _only_ this code and see if it demonstrates the problem. We should not be looking at a fragment of a much larger program. – H H Jun 10 '18 at 14:57
  • 1
    @Fabjan - that is a horrible brute force approach. Maybe it will be needed but the OP should look for other options first. – H H Jun 10 '18 at 14:59
  • @HenkHolterman By all means I'm not suggesting it as a solution. It's merely a small test... It's weird though that `DownloadStringTaskAsync` is blocking the thread. – Fabjan Jun 10 '18 at 15:00
  • It shouldn't. And therefore I'm not ruling out `new WebClient`, that is a strange class. – H H Jun 10 '18 at 15:01
  • @StepUp As an aside: you could remove `async` keyword from method signature and return a `Task` object directly - `return webClient.DownloadStringTaskAsync(url);` – Fabjan Jun 10 '18 at 15:03
  • @HenkHolterman I see that it should work okay. However, I've created a scrap project with only this code and problem is always occurred, but only when I click the button at the first time. – StepUp Jun 10 '18 at 15:04
  • @StepUp Maybe you've some stuff not related to this in the UI that is initializing and blocking the thread ? – Fabjan Jun 10 '18 at 15:05
  • OK, try creating a single WebCLient in the constructor or OnLoad. Just a hunch. – H H Jun 10 '18 at 15:05
  • @Fabjan no, just this code and nothing more. – StepUp Jun 10 '18 at 15:05
  • @HenkHolterman yeah, I've created a single WebCLient in the constructor, but there is still some UI freezing for 5 seconds. – StepUp Jun 10 '18 at 15:08
  • @Fabjan `As an aside: you could remove async keyword from method signature and return a Task object directly - return webClient.DownloadStringTaskAsync(url);` I've tried it, but there is still some UI freezing for 5 seconds. – StepUp Jun 10 '18 at 15:11
  • Yes, 'eliding async' is a small optimization but it couldn't have helped here. – H H Jun 10 '18 at 15:13
  • 1
    It is not the async mechanism that is blocking you here, it is WebClient and/or your network layer. – H H Jun 10 '18 at 15:14
  • See for instance [this question](https://stackoverflow.com/q/10568321/60761), I think you have the same problem Also worth a try: HttpClient. Use it as a singleton. – H H Jun 10 '18 at 15:16
  • When it freezes, press pause in the debugger.... what's it doing? – MineR Jun 10 '18 at 16:52
  • @HenkHolterman please, write your reply to use `HttpClient`, and I'll mark as answer. You are right. Now UI is not freezed when I click at the button at the first time. – StepUp Jun 10 '18 at 18:50
  • 1
    You can post a self-answer... I was just guessing. Maybe somenody comes along to tell us why HttpClient does better. – H H Jun 10 '18 at 20:02

3 Answers3

1

There could be some caching. Try another URL each call. But with await it should not be blocking.

I tested and I have no lag. I would start a fresh client. Something strange is going on.

Put in some Stopwatch Debug to try and figure where the lag is.

private async void btnURLclick(object sender, RoutedEventArgs e)
{
    Stopwatch sw = new Stopwatch();
    sw.Start();
    var html = await GetHtmlAsync("http://msdn.microsoft.com");
    Debug.WriteLine($"btn {sw.ElapsedMilliseconds}");
    MessageBox.Show(html.Substring(0, 10));

}
public async Task<string> GetHtmlAsync(string url)
{
    Stopwatch sw = new Stopwatch();
    sw.Start();
    var webClient = new WebClient();
    Debug.WriteLine($"taskA {sw.ElapsedMilliseconds}");
    return await webClient.DownloadStringTaskAsync(url);
}
paparazzo
  • 44,497
  • 23
  • 105
  • 176
  • This will not tell you what part is freezing. – H H Jun 10 '18 at 16:44
  • The OP has already established that it is the `DownloadStringTaskAsync()` call... We have eliminated `new WebClient()` , that wasn't to likely anyway. – H H Jun 10 '18 at 16:53
  • @HenkHolterman I am not seeing where that is established. It is not going to hurt to get some numbers. Moving on. – paparazzo Jun 10 '18 at 17:02
1

The HttpClient is the way to go but let's look at code.

Pulling the code for the corefx source. If you're actually getting a HttpWebRespone this snippet may point to the issue your seeing.

public override Stream GetResponseStream()
{
    CheckDisposed();
    return _httpResponseMessage.Content.ReadAsStreamAsync().GetAwaiter().GetResult();
}
JSteward
  • 6,833
  • 2
  • 21
  • 30
-1

That's probably due to some communications initialization. Try this:

public async Task<string> GetHtmlAsync(string url)
{
    await Task.Delay(1).ConfigureAwait(false);
    var webClient = new WebClient();
    return await webClient.DownloadStringTaskAsync(url).ConfigureAwait(false);
}
H H
  • 263,252
  • 30
  • 330
  • 514
Paulo Morgado
  • 14,111
  • 3
  • 31
  • 59