Question

I have following code,

using System;
using System.Threading.Tasks;


namespace asyncawait
{
    class Practice
    {
       async Task<int>  Method()
        {
            for (int i = 0; i < int.MaxValue ; i++);

            return 10;
        }

       public async void caller()
        {

           int a = await Method();
           Console.WriteLine("Please print it first");
           Console.WriteLine(a);
           Console.WriteLine("Please print it last");

        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            Practice p = new Practice();
            p.caller();
        }
    }
}

Warning While Building Project:

Program.cs(9,25,9,31): warning CS1998: This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.

My expectation was,

Expected Output: (First line should get immediately printed)

Please print it first // no wait because I am not using a and function is await
10
Please print it last

Actual Output:

Please print it first // waiting to execute function then prints output
10
Please print it last

I do not understand, why my function is taking time cannot work asynchronous? I am really not able to understand concept after looking at lot many examples.

Was it helpful?

Solution

all the async keyword does is allow you to use the await keyword inside a function. If you don't call await the function behaves the same as if you did not do any async keyword at all.

Take a look at this image from the msdn page "Asynchronous Programming with Async and Await (C# and Visual Basic)"

enter image description here

If you follow the black line all that happens on the same thread, unbroken until you get to 6. Then at that point the function returns and continues later when the results are ready. Because you don't have a await in your code your "black line" goes through your entire function.

To make it work like you want to you need to signal in the function where it should go back to the caller.

   async Task<int>  Method()
    {
        for (int i = 0; i < int.MaxValue ; i++)
        {
            await Task.Yield(); //Your function now returns to the caller at this point then comes back later to finish it. (Your program will be much slower now because it is going to wait int.MaxValue times.)
        }
        return 10;
    }

OTHER TIPS

When you use the await keyword, you are telling the current method to wait for the result of the Task you pass to it. The magic comes from the fact that while waiting, the method is suspended and the calling thread can go on with other work.

When you put await Method() as your first statement, the rest of the function is executed only after the result of Method() is available, regardless of what is happening outside the function in between. To achieve the behavior you want, you should fire the task first, then print the first line, and then wait for the result. That is:

public async void caller() {
    var a = Method();   // <- The task is running now asynchronously
    Console.WriteLine("Please print it first"); // <- The line is printed.
    Console.WriteLine(await a); // <- the result of a is waited for and printed when available.
    Console.WriteLine("Please print it last");
}

Also note that the Method is not executed asynchronously just because of the async keyword. To create a asynchronous method, you should return a Task, for example:

Task<int> Method() {
    return Task.Run( () => {
        // ... the previous function body...
    });
}

Try to replace code of your Main() method with following:

Task.Run(
() =>
{
      Practice p = new Practice();
      p.caller();
});

You will get your answer.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top