[c#] Run two async tasks in parallel and collect results in .NET 4.5

I've been trying for a while to get something I thought would be simple working with .NET 4.5

I want to fire off two long running tasks at same time and collect the
results in in the best C# 4.5 (RTM) way

The following works but I don't like it because:

  • I want Sleep to be an async method so it can await other methods
  • It just looks clumsy with Task.Run()
  • I don't think this is even using any new language features at all!

Working code:

public static void Go()
{
    Console.WriteLine("Starting");

    var task1 = Task.Run(() => Sleep(5000));    
    var task2 = Task.Run(() => Sleep(3000));

    int totalSlept = task1.Result + task2.Result;

    Console.WriteLine("Slept for a total of " + totalSlept + " ms");
}

private static int Sleep(int ms)
{
    Console.WriteLine("Sleeping for " + ms);
    Thread.Sleep(ms);
    Console.WriteLine("Sleeping for " + ms + " FINISHED");
    return ms;
}

Non working code:

Update: This actually works and is the correct way to do it, the only problem is the Thread.Sleep

This code doesn't work because the call to Sleep(5000) immediately starts the task running so Sleep(1000) doesn't run until it has completed. This is true even though Sleep is async and I'm not using await or calling .Result too soon.

I thought maybe there is a way to get a non-running Task<T> by calling an async method so I could then call Start() on the two tasks, but I can't figure out how to get a Task<T> from calling an async method.

public static void Go()
{
    Console.WriteLine("Starting");

    var task1 = Sleep(5000);    // blocks
    var task2 = Sleep(1000);

    int totalSlept = task1.Result + task2.Result;

    Console.WriteLine("Slept for " + totalSlept + " ms");
}

private static async Task<int> Sleep(int ms)
{
    Console.WriteLine("Sleeping for " + ms);
    Thread.Sleep(ms);
    return ms;
}

This question is related to c# asynchronous task-parallel-library .net-4.5

The answer is


This article helped explain a lot of things. It's in FAQ style.

Async/Await FAQ

This part explains why Thread.Sleep runs on the same original thread - leading to my initial confusion.

Does the “async” keyword cause the invocation of a method to queue to the ThreadPool? To create a new thread? To launch a rocket ship to Mars?

No. No. And no. See the previous questions. The “async” keyword indicates to the compiler that “await” may be used inside of the method, such that the method may suspend at an await point and have its execution resumed asynchronously when the awaited instance completes. This is why the compiler issues a warning if there are no “awaits” inside of a method marked as “async”.


async Task<int> LongTask1() { 
  ...
  return 0; 
}

async Task<int> LongTask2() { 
  ...
  return 1; 
}

...
{
   Task<int> t1 = LongTask1();
   Task<int> t2 = LongTask2();
   await Task.WhenAll(t1,t2);
   //now we have t1.Result and t2.Result
}

To answer this point:

I want Sleep to be an async method so it can await other methods

you can maybe rewrite the Sleep function like this:

private static async Task<int> Sleep(int ms)
{
    Console.WriteLine("Sleeping for " + ms);
    var task = Task.Run(() => Thread.Sleep(ms));
    await task;
    Console.WriteLine("Sleeping for " + ms + "END");
    return ms;
}

static void Main(string[] args)
{
    Console.WriteLine("Starting");

    var task1 = Sleep(2000);
    var task2 = Sleep(1000);

    int totalSlept = task1.Result +task2.Result;

    Console.WriteLine("Slept for " + totalSlept + " ms");
    Console.ReadKey();
}

running this code will output :

Starting
Sleeping for 2000
Sleeping for 1000
*(one second later)*
Sleeping for 1000END
*(one second later)*
Sleeping for 2000END
Slept for 3000 ms

It's weekend now!

    public async void Go()
    {
        Console.WriteLine("Start fosterage...");

        var t1 = Sleep(5000, "Kevin");
        var t2 = Sleep(3000, "Jerry");
        var result = await Task.WhenAll(t1, t2);

        Console.WriteLine($"My precious spare time last for only {result.Max()}ms");
        Console.WriteLine("Press any key and take same beer...");
        Console.ReadKey();
    }

    private static async Task<int> Sleep(int ms, string name)
    {
            Console.WriteLine($"{name} going to sleep for {ms}ms :)");
            await Task.Delay(ms);
            Console.WriteLine("${name} waked up after {ms}ms :(";
            return ms;
    }

While your Sleep method is async, Thread.Sleep is not. The whole idea of async is to reuse a single thread, not to start multiple threads. Because you've blocked using a synchronous call to Thread.Sleep, it's not going to work.

I'm assuming that Thread.Sleep is a simplification of what you actually want to do. Can your actual implementation be coded as async methods?

If you do need to run multiple synchronous blocking calls, look elsewhere I think!


Examples related to c#

How can I convert this one line of ActionScript to C#? Microsoft Advertising SDK doesn't deliverer ads How to use a global array in C#? How to correctly write async method? C# - insert values from file into two arrays Uploading into folder in FTP? Are these methods thread safe? dotnet ef not found in .NET Core 3 HTTP Error 500.30 - ANCM In-Process Start Failure Best way to "push" into C# array

Examples related to asynchronous

How to read file with async/await properly? Use Async/Await with Axios in React.js Waiting until the task finishes How to reject in async/await syntax? React - Display loading screen while DOM is rendering? angular 2 how to return data from subscribe How do I access store state in React Redux? SyntaxError: Unexpected token function - Async Await Nodejs Why does .json() return a promise? Why is setState in reactjs Async instead of Sync?

Examples related to task-parallel-library

What is the difference between Task.Run() and Task.Factory.StartNew() Task.Run with Parameter(s)? HttpClient - A task was cancelled? Running multiple async tasks and waiting for them all to complete Deserialize JSON to Array or List with HTTPClient .ReadAsAsync using .NET 4.0 Task pattern Calling async method synchronously How can I tell Moq to return a Task? When to use Task.Delay, when to use Thread.Sleep? Awaiting multiple Tasks with different results How to safely call an async method in C# without await

Examples related to .net-4.5

There is no argument given that corresponds to the required formal parameter - .NET Error The type or namespace name 'System' could not be found Which versions of SSL/TLS does System.Net.WebRequest support? async at console app in C#? Is it possible to run a .NET 4.5 app on XP? Awaiting multiple Tasks with different results Do you have to put Task.Run in a method to make it async? C# HttpClient 4.5 multipart/form-data upload Do HttpClient and HttpClientHandler have to be disposed between requests? What is the correct way to read a serial port using .NET framework?