简体   繁体   中英

Async Task not running in background?

I was playing with Async and made a sample program below. The sample program compares time spent for synchronous and asynchronous operations

I was expecting that async operations will take lesser time, considering that tasks run in parallel on background thread. But the program below takes equal time for both sync and async operations. I think I am missing something, but everywhere I get the following example to create async task and run them

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace AsyncTest {
    class Program {

    private static long max = 100;

    static void Main(string[] args) {
        var startTime = DateTime.Now;
        Console.WriteLine("Start Process at");

        //Normal();    //takes about 20 secs
        MainAsync().Wait();     //takes about 20 secs

        Console.WriteLine($"Total Time Taken {DateTime.Now.Subtract(startTime).TotalMilliseconds} ms");
        Console.ReadKey();

    }

    static void Normal() {
        for (long i = 0; i <= max; ++i) {
            Thread.Sleep(200);
        }
    }

    static async Task MainAsync() {
        var runner = new Runner();

        for (int i = 0; i <= 100; ++i) {
            await runner.Run(i, max / 100);
        }
    }

}

public class Runner {
    public async Task Run(int idx, long max) {
        await Task.Run(() => {
            for (long i = 1; i <= max; ++i) {
                Console.WriteLine($"Task {idx} - {i}");
                Thread.Sleep(200);
            }
        });
    }
}

}

Any help what am I missing here ?

The first problem is that you still run the tasks sequentially:

for (int i = 0; i <= 100; ++i) {
    await runner.Run(i, max / 100);
}

You start the task, wait until it is completed and only then continue iteration. Just change it to:

await Task.WhenAll(Enumerable.Range(0, 101).Select(i => runner.Run(i, max / 100)));

The second problem is using synchronous Thread.Sleep call. Replace Thread.Sleep(200) with await Task.Delay(200) . It is ok to use Thread.Sleep to simulate some work but never use it with TPL (async-await) when you want just to wait.

In my opinion you made the mistake of starting MainAsync with .Wait() which will block until the task is done. Within MainAsync you maybe assume to start runner a hundred times but in reality you wait (by using await ) in each iteration of the for -loop to finish runner.Run() . And in the Run method of the Runner class you start Task where you are waiting (by using await ) until it finishes too. You also use a synchronous Thread.Sleep call which should be replaced by await Task.Delay() .

So in summary you are using await everywhere which results in waiting for the task until it has finished its execution.

What you could do eg is creating those Task instances, starting them and then use await to wait for them all.

As example a method that does "some heavy work":

static async Task DoHeavyWork(int idx, int max)
{
    for (long i = 1; i <= max; ++i)
    {
        Console.WriteLine($"Task {idx} - {i}");
        await Task.Delay(200);
    }
}

Now let us "start" them and until all of them are finished:

static void Main(string[] args)
{
    int max = 10;
    List<Task> tasks = new List<Task>();

    for (int i = 0; i <= max; ++i)
    {
        tasks.Add(DoHeavyWork(i, max));
    }

    Task.WaitAll(tasks.ToArray());
}

If you set a breakpoint at Task.WaitAll you will see, that you will hit this breakpoint before all tasks have finished their execution (what has been the idea behind this complete scenario in the first place ;-) ).

You can speed up things only if you:

1) have more then one processor

2) and can split the task to parallise it on the processors.

But in your example you are only waiting, nothing to parallise. So no speed up.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM