Runtime: HttpClient Async calls still block the current (UI) thread

Created on 15 Oct 2020  路  8Comments  路  Source: dotnet/runtime

Description

when I perform an async call on HttpClient from the (Winforms) UI thread my UI gets blocked. its best noticed when moving the window around.

If I wrap the call in Task.Run the app runs smooth.

var items = await HttpClient.GetStuffAsync();

vs 

var items = await task.Run((() => HttpClient.GetStuffAsync());

my expectaion is that the async methods dont block the current thread.

area-System.Net.Http question untriaged

Most helpful comment

You aren't using ConfigureAwait(false) prior to waiting the task from HttpClient.GetStuffAsync() and because it's winforms there will be a synchronisation context active so the task scheduler will attempt to push completions back to the main thread. Try with the configuration and see if it helps.

All 8 comments

Tagging subscribers to this area: @dotnet/ncl
See info in area-owners.md if you want to be subscribed.

You aren't using ConfigureAwait(false) prior to waiting the task from HttpClient.GetStuffAsync() and because it's winforms there will be a synchronisation context active so the task scheduler will attempt to push completions back to the main thread. Try with the configuration and see if it helps.

because it's winforms there will be a synchronisation context

In combination with ConfigureAwait(false) it can give you a System.InvalidOperationException, if in the continuation you'll access controls (UI thread).

the async methods dont block the current thread.

I didn't investigate the problem, but it seems as the async request doesn't block the UI-thread, but the continuation / the processing of the results (e.g. a huge string).

Try to just use the status-code from the response and not the actual content, then it runs smooth in my demo.
With a huge content from the response it's smooth while the fetch happens, then it starts to block the UI-thread.

In combination with ConfigureAwait(false) it can give you a System.InvalidOperationException, if in the continuation you'll access controls (UI thread).

Yes, that is expected. You should follow the normal winforms rules around checking for and marshalling back to the UI thread. If you want long running work not to block the UI thread then it needs to happen on a separate thread and if you use a separate thread you have to be careful to push updates back onto the UI thread.

You aren't using ConfigureAwait(false) prior to waiting the task from HttpClient.GetStuffAsync()

I have a workaround that unblocks the UI.

my issue is why do I need workarounds?

why doesnt the http client send my request in an async fashion and unblock the UI thread?
because that is what having an async get method implies for me!

want long running work not to block the UI thread then it needs to happen on a separate thread

what is the longrunning work that is happening in the ui thread? im using an async method!

why doesnt the http client send my request in an async fashion and unblock the UI thread?
because that is what having an async get method implies for me!

It does, the waiting is done on another thread but any subsequent code will come back to the main thread.
Unless you can demonstrate that the async wait itself (not following work) blocks the UI thread then this is working as expected to me.

I think you need to do some reading into how async works and change your expectations from magical thinking to reality based.

Unless you can demonstrate that the async wait itself (not following work) blocks the UI thread then this is working as expected to me.

It wouldn't be the first time. I think in early versions the proxy was resolved synchronously before the actual asynchronous call.

@JanEggers To stop any controversy, could you try changing your code to:

_ = HttpClient.GetStuffAsync();

and see if the issue persists? Basically removing any work, and just leaving the synchronous part of the HttpClient call.

@kevingosse thx to pointing me in the right direction.

the issue was that the payload deserialization was blocking the ui thread.

with my additional task run the serialization happens in the background and without it in the ui.

that was not obvious to me as the code generated by nswag uses configurawait(false) so i thought deserializations happens in the background.

anyway thx for clarifiing

Was this page helpful?
0 / 5 - 0 ratings

Related issues

jamesqo picture jamesqo  路  3Comments

yahorsi picture yahorsi  路  3Comments

bencz picture bencz  路  3Comments

nalywa picture nalywa  路  3Comments

v0l picture v0l  路  3Comments