Search code examples
c#.netasync-awaittask.net-4.6

How to declare a not started Task that will Await for another Task?


I've done this Unit Test and I don't understand why the "await Task.Delay()" doesn't wait !

   [TestMethod]
    public async Task SimpleTest()
    {
        bool isOK = false;
        Task myTask = new Task(async () =>
        {
            Console.WriteLine("Task.BeforeDelay");
            await Task.Delay(1000);
            Console.WriteLine("Task.AfterDelay");
            isOK = true;
            Console.WriteLine("Task.Ended");
        });
        Console.WriteLine("Main.BeforeStart");
        myTask.Start();
        Console.WriteLine("Main.AfterStart");
        await myTask;
        Console.WriteLine("Main.AfterAwait");
        Assert.IsTrue(isOK, "OK");
    }

Here is the Unit Test output :

Unit Test Output

How is this possible an "await" doesn't wait, and the main thread continues ?


Solution

  • new Task(async () =>

    A task does not take a Func<Task>, but an Action. It will call your asynchronous method and expect it to end when it returns. But it does not. It returns a task. That task is not awaited by the new task. For the new task, the job is done once the method returned.

    You need to use the task that already exists instead of wrapping it in a new task:

    [TestMethod]
    public async Task SimpleTest()
    {
        bool isOK = false;
    
        Func<Task> asyncMethod = async () =>
        {
            Console.WriteLine("Task.BeforeDelay");
            await Task.Delay(1000);
            Console.WriteLine("Task.AfterDelay");
            isOK = true;
            Console.WriteLine("Task.Ended");
        };
    
        Console.WriteLine("Main.BeforeStart");
        Task myTask = asyncMethod();
    
        Console.WriteLine("Main.AfterStart");
    
        await myTask;
        Console.WriteLine("Main.AfterAwait");
        Assert.IsTrue(isOK, "OK");
    }