async Task<bool> method call in if condition

12,964

Solution 1

I would like to know if the following code will wait for the async method to complete before executing the main thread or will just continue the main thread if condition and consider the method return as false.

Neither.

await is an "asynchronous wait". In other words, the method will wait, but the thread will not.

When your method hits that await (assuming it actually has some waiting to do), it will immediately return an incomplete task to the caller of SomeMethod. The thread continues with whatever it wants to do. Later on, when the task being awaited completes, then SomeMethod will resume executing. When SomeMethod completes, the task it returned earlier will be completed.

I go into more detail on my blog post on the subject.

Solution 2

It will wait for the operation to complete.

Note how you're invoking the operation:

if(await AsyncMethod(param))

Two things:

  1. Using the await keyword will, unsurprisingly, wait for the operation to complete.
  2. If it didn't wait for the operation to complete then this would be a compiler error. Because while a bool can be used in a conditional, a Task<bool> can not.

Solution 3

awaiting an async method will cause the calling thread to return from the method caller until the async method completes. Once the method completes, the calling thread (in a synchronized context) will switch back to where it left off. Without a synchronization context, the await method will still return back to the caller and execution of the calling method will resume (but not necessarily on the same thread it was originally called from). This will happen regardless of the return type/value.

In your case (assuming the syntax is correct). SomeMethod (you need to add ()) will call AsyncMethod and return immediately. Once AsyncMethod is done, SomeMethod will switch back to where it left off, which is evaluating the returned value (true or false). If the value is true it will call //Do something, otherwise it will skip the if statement and finish executing SomeMethod.

Here is an example of where there is no synchronization context. Notice the thread id changes after "await getStringTask", and the rest of GetValue is executed on the "new" thread.

    private static void Main(string[] args)
    {
        GetValue();
        Console.WriteLine("test1");
        Console.WriteLine("1 " + Thread.CurrentThread.ManagedThreadId);
        Console.ReadKey();
    }

    private static async void GetValue()
    {
        Console.WriteLine(await AccessTheWebAsync());
        Console.WriteLine("2 " + Thread.CurrentThread.ManagedThreadId);
        Console.WriteLine("test2");
        Console.WriteLine("3 " + Thread.CurrentThread.ManagedThreadId);
    }

    private static async Task<int> AccessTheWebAsync()
    {
        HttpClient client = new HttpClient();
        Task<string> getStringTask = client.GetStringAsync("http://msdn.microsoft.com");
        Console.WriteLine("4 " + Thread.CurrentThread.ManagedThreadId);
        string urlContents = await getStringTask;
        Console.WriteLine("5 " + Thread.CurrentThread.ManagedThreadId);
        return urlContents.Length;
    }

Prints

4 9
test1
1 9
5 13
47984
2 13
test2
3 13
Share:
12,964
liferunsoncode
Author by

liferunsoncode

My first rendezvous with computers was when I was in 5th grade and wrote programs in Logo and Basic languages. Ever since then have been a computer student and then a computer science engineer. I love programming and have worked on C, C++, C#, Java and also Mainframes (COBOL) too. I love programming challenges and always eager to learn about the latest developments in technology. I love playing computer games specially adventure and strategy ones.

Updated on July 29, 2022

Comments

  • liferunsoncode
    liferunsoncode almost 2 years

    I would like to know if the following code will wait for the async method to complete before executing the main thread or will just continue the main thread if condition and consider the method return as false.

    public async Task<bool> SomeMethod
    {
        if(await AsyncMethod(param))
        {
            //Do something
        }
    }
    

    ...

    And the async method is defined as:

    public async Task<bool> AsyncMethod(SomeClass param)
    {
       //Do something
    }
    
  • Servy
    Servy about 8 years
    Once the method completes, the calling thread will switch back to where it left off. This can happen, as a result of synchronization context, but it doesn't necessarily happen. It's not inherent to await that this happens. SomeMethod will call AsyncMethod on a ThreadPool There's no code shown to indicate this. AsyncMethod is asynchronous, but that doesn't mean a thread pool thread is necessarily involved at all.
  • Tom
    Tom about 8 years
    In my experience, once an awaited method completes, the calling thread context switches back to where it left off. Care to explain a case where it will not?
  • Servy
    Servy about 8 years
    If your only experience is using await in a UI context where there is a synchronization context, then yes, that's what you'd see, because that's what happens in that situation, but that won't always be the case. There won't be a synchronization context in all situations. As far as the thread pool is concerned, there are lots of ways to create asynchrony, using a separate thread is just one. The other extremely common action would be IO.
  • Tom
    Tom about 8 years
    I understand it may not be executed on a separate thread, and I edited my answer for correctness. You said it doesn't necessarily return back to where it left off. I am wondering in what case this will happen (aside from the program ending before it can finish)?
  • Servy
    Servy about 8 years
    The async method will always return to its caller as soon as it has resolved the awaitable object to its value, that's not the statement of yours I quoted and commented on. It's the statement that the calling thread is handling the continuation that is sometimes true, but not necessarily true.
  • Tom
    Tom about 8 years
    Thanks @Servy, I updated my answer for correctness and added an example of how it will behave in a non-synchronized context.