Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

I'm trying to learn async/await and created the following test code, however it is running synchronously and I'm not sure why.

    class Program
    {                
        static void Main()
        {
            TestAsync testAsync = new TestAsync();
            testAsync.Run();

            Console.Read();
        }        
    }

    public class TestAsync
    {
        public async void Run()
        {
            Task<int> resultTask = GetInt();
            Console.WriteLine("2)");
            int x = await resultTask;
            Console.WriteLine("4)");
        }
        public async Task<int> GetInt()
        {
            Task<int> GetIntAfterLongWaitTask = GetIntAfterLongWait();
            Console.WriteLine("1)");
            int x = await GetIntAfterLongWaitTask;//Expecting execution to go back to Run() since it's not done yet.
            Console.WriteLine("3)");
            return x;
        }

        public async Task<int> GetIntAfterLongWait()
        {
            for (int i = 0; i < 500000000; i++)
            {
                if (i % 10000000 == 0)
                {
                    Console.WriteLine(i);
                }                
            }

            return 23;
        }
    }

Output is:

<long list of ints>
1)
3)
2)
4)

I expected it to be

<long list of ints>
1)
2)
3)
4)

With 1) being somewhere amongst the long list of ints.

Why is it running synchronously?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
345 views
Welcome To Ask or Share your Answers For Others

1 Answer

Confusingly enough, the async keyword will not turn your methods magically asynchronous. Instead, you can consider async methods as a setup for a state machine (see a detailed explanation here), where you schedule the chain of operations by the await calls.

For that reason, your async methods must execute as fast as possible. Do not do any blocking operation in such a setup method. Your GetIntAfterLongWait method is a blocking operation and since it does not contain any awaits the whole content will be executed immediately when the method is called (without any await there is nothing in the method to setup for an async continuation). There must be also a warning about that.

If you have a blocking operation, which you want to execute in the async method, a possible option is to schedule it by an await Task.Run(() => MyLongOperation()); call.

So for example the following example will return immediately because there is nothing to execute before the first await. The return statement will be executed asynchronously as a continuation after the inner awaited task finished:

public async Task<int> GetIntAfterLongWait()
{
    await Task.Run(() =>
    {
        for (int i = 0; i < 500000000; i++)
        {
            if (i % 10000000 == 0)
            {
                Console.WriteLine(i);
            }                
        }
    });

    return 23;
}

For more details see the link above.

Update:

This version will print:

1)
2)
<long list of ints> - but 0 can be before even 1) as Task.Run uses another thread
3)
4)

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
...