Why awaiting cold Task does not throw

async-await, asynchronous, c#

Solution

You're trying to start the task returned by the async method - that isn't the cold task that you started out with. Indeed, if you add some diagnostics to your `Task.Run` call, you'll see that an exception is thrown:

System.InvalidOperationException: Start may not be called on a promise-style task.

Here's an example showing what I think you were really trying to do:

using System;
using System.Threading;
using System.Threading.Tasks;

public class Test
{
    static void Main(string[] args)
    {
        // Not using Task.Delay! That would be pointless
        Task t1 = new Task(() => Thread.Sleep(1000));
        Task t2 = Await(t1);
        Console.WriteLine(t2.Status);
        Console.WriteLine("Starting original task");
        t1.Start(); 
        Console.WriteLine(t2.Status);
        t2.Wait();
        Console.WriteLine(t2.Status);        
    }

    static async Task Await(Task task)
    {
        Console.WriteLine("Beginning awaiting");
        await task;
        Console.WriteLine("Finished awaiting");        
    }
}

Note the use of `Thread.Sleep` instead of `Task.Delay`; unless you're using the result of `Task.Delay`, it basically does nothing. Using `Thread.Sleep` is emulating real work to be done in the other task.

As for why awaiting an unstarted task doesn't throw an exception - I think that's reasonable, to be honest. It allows for situations like the above to be valid, which may in some cases make life easier. (You may create a lot of tasks before starting them, for example - and you may want to start waiting for them to finish before you start them.)

Problem

I was just experimenting to see what happens when a cold task (i.e. a `Task` which hasn't been started) is awaited. To my surprise the code just hung forever and "Finsihed" is never printed. I would expect that an exception is thrown. ``` public async Task Test1() { var task = new Task(() => Thread.Sleep(1000)); //task.Start(); await task; } void Main() { Test1().Wait(); Console.WriteLine("Finished"); } ``` Then I though perhaps the task can be started from another thread, so I changed the code to: ``` public async Task Test1() { var task = new Task(() => Thread.Sleep(1000)); //task.Start(); await task; Console.WriteLine("Test1 Finished"); } void Main() { var task1 = Test1(); Task.Run(() => { Task.Delay(5000); task1.Start(); }); task1.Wait(); Console.WriteLine("Finished"); } ``` But it is still blocked at `task1.Wait()`. Does anyone know if there is way to start a cold task after it has being awaited? Otherwise it seems there is no point in being able to `await` a cold task, so perhaps the task should either be started when awaited or an exception should be thrown. Update I was awaiting the wrong task, i.e. the outer task returned by `Test1` rather than the one newed inside it. The InvalidOperationException mentioned by @Jon Skeet was being thrown inside `Task.Run` however because the resulting task was not observed, the exception was not thrown on the main thread. Putting a `try/catch` inside `Task.Run` or calling `Wait()` or `Result` on the task returned by `Task.Run` threw the exception on the main console thread.

Original source