0

I just learned some more about async await. I used to think everything in an async Task method just gets executed on a background thread. Now I understand that's not the case and went to refactor some of my code so its blocking less of my UIThread (WPF).

This is my "normal" async method:

public async Task<List<Data>> DoSomethingAsync(){
    var data = dbContext.Data.ToListAsync(); // <- Executes on a background thread internally
    ... // <- Executes on UIThread
    return dataList;
}

If I call that method in a ViewModel now, it will not actually be executed on a background. To do that I have to call Task.Run(DoSomethingAsync);.

I didnt want to just blindly wrap all my calls to async methods into Task.Run, so I found myself checking the implementation of every single method whether it has "..." content or is just wrapping an async method from ef core/http/filesystem.

What is the general idea here? Should all my async methods just look like this by default?

public Task<List<Data>> DoSomethingAsyncActuallyInBackground() {
    return Task.Run(() => {
        var data = dbContext.Data.ToListAsync();
        ... 
        return dataList;
    }
}

I feel like the first method is somehow "lying". It says Async, but calling it I have actually no idea whether it is truly asynchronous/non blocking code. Internally ef cores ToListAsync() works on a background thread right? Thats how its possible for it to be non blocking.

I am now realizing that I equate "asynchronous" with "on a background thread / non blocking". Is this even true?

6

1 Answer 1

2

I am now realizing that I equate "asynchronous" with "on a background thread / non blocking". Is this even true?

Asynchronous does mean "nonblocking", but "asynchronous" (in the modern sense of the word, as used by async/await) does not necessarily mean "on a background thread".

I recommend starting with my async intro and following up with There Is No Thread. Consider the case of a database query: once the query is sent to the db server, there's no need for a thread to just sit there blocking, waiting for a response. Asynchronous code frees up that thread to do other things, and uses a Task<T> (a.k.a. "promise") to notify the application when the query results have arrived from the db server.

Sign up to request clarification or add additional context in comments.

4 Comments

Is there such a thing as being "too async"? Take for example the XmlWriter class with its WriteXXXAsync methods that would typically write out just a few bytes at a time. It would seem that the overhead of awaiting each individual call would greatly outweigh just a single await on an XElement.WriteToAsync for example.
Yes, there is such a thing as "too async". The "chatty" interfaces like that can cause performance problems if called at scale. ValueTask mitigates these performance problems, but methods that do very little I/O and also return Task can be problematic. I usually try to do formatting in-memory and then (asynchronously) write out the complete string all at once.
That's what I figured, and was very surprised to see those types of methods implemented in the XmlWriter class. Now I'm curious as to why they thought it necessary to include them.
@mford: I have seen multi-GB XML files that require streaming. Sad, but true.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.