Cruces
Cruces

Reputation: 3119

Questions about what runs on the main thread during c#'s async await

I'm having trouble understanding what runs on the main thread during an async await operation and would be grateful for some answers.

Let's say I have a button that is supposed to log the user in.

it is supposed to block all other user input while the login process transpires, show a progress view and then when the result comes in display it

and here is the method that performs the log in

button_clicked(object sender, EventArgs e) {
    do_login(); //I do not await the result
    do_some_other_stuff(); //this doesn't actually exist I just put it here to ask my questions
}

async Task do_login() {
    string user_name = txtUser.Text;
    string password = txtPassword.Text;
    show_progress(true); //this is not an async method;
    string error = await _login.do_login(user_name, password);//this is an async method that can take up to 20 seconds to complete;
    show_progress(false);
    if (error != null) {
        show_error(error);
    } else {
        show_next_screen();
    }
}

I have two questions on the above example

a) What will be run on the main thread?

If I understand it correctly only _login.do_login will be run on a seperate thread, all others will be on the main thread, is this correct?

b) In what order will the methods be executed?

Again if I understand it correctly, it will be :

is this correct? if not, how can I achieve such a behaviour?

c) If my code above is correct then why do I keep receiving a warning that do_login() is not awaited? I do not wish to await it I just want it to run what it can and return when it wants, should I ignore that warning?

Upvotes: 0

Views: 62

Answers (2)

Oscar Paz
Oscar Paz

Reputation: 18292

Technically, depending on the implementation of do_login, everything could run in the main thread. In this case I assume you're contacting a web server, so that part won't, but this is not always true. And asynchronous operation does not necessarily executes in another thread. One operation is asynchronous when:

  • It doesn't block the calling thread.

Usually, UI threads run an 'event loop'. So an asynchronous task could simply put a new piece of work into the event queue to be executed whenever the scheduler determines, but in the same thread. In this case you don't use two threads, but still, you don't have to wait for the task to complete and you don't know when it'll finish.

To be precise, all the code in your post will run in the main thread. Only the part in do_login that manages the connection with the server, waiting and retrieving data will execute asynchronously.

You're mostly right about the sequence, with a few adjustments:

  1. do_login() (until the await)
  2. login._do_login() starts executing
  3. do_some_other_stuff()
  4. ...
  5. login.do_login finishes
  6. show_progress()

Upvotes: 2

BradleyDotNET
BradleyDotNET

Reputation: 61349

The answer to your main question is: it depends. The _login.do_login method will likely be put onto its own thread, but it actually depends on the .NET task scheduler. In WPF and ASP.NET it will be scheduled onto the thread pool if it doesn't immediately return a completed task.

The important part is that you know it will not block execution of the calling (in your case, the main) thread. Your understanding of the method flow is correct since you don't await do_login.

As far as the warning goes; you can mark do_login as async void to avoid it, though generally you only do that for event handlers which can then await a Task returning method. If you do go the async void route; make sure to put a try/catch in as such methods will throw all the way up to the root handler and can cause your app to crash.

Upvotes: 1

Related Questions