Task status changes to RanToCompletion if the Task await's something

.net, .net-4.5, async-await, asynchronous, c#

Solution

I can reproduce this issue with far less code:

void Main()
{
    Task t1 = Task.Factory.StartNew(Accept);
    t1.Wait();
    Console.WriteLine("Main ended");
}

public static async void Accept()
{
    while (true)
    {
        await Task.Delay(1000);
    }

    Console.WriteLine("Stoppped");
}

But this works correctly:

void Main()
{
    Task t1 = Accept();
    t1.Wait();
    Console.WriteLine("Main ended");
}

public static async Task Accept()
{
    while (true)
    {
        await Task.Delay(1000);
    }

    Console.WriteLine("Stoppped");
}

Basically, by using `Task.Factory.StartNew()`, you are creating a `Task` based on a separate thread getting spawned to invoke the given delegate (the `Accept()` method). The `Accept` method itself (like any good `async` method) actually returns immediately. So the thread that calls it finishes its task immediately, so the `Task` created to represent that thread also finishes immediately.

If you allow `Accept()` to return a `Task` instead of `void`, then the `Task` that it returns is what you should be awaiting if you want to wait until it has run through all its `await`s.

Problem

The question describes the same problem found here - MSDN Developer Forum. The question does not have an accepted answer, neither any of the answers given can be applied to my case (hence a different question). Question is also derived from one I asked previously, but, due to different nature and more specific problem, I'm asking a new one. Full code can be found here: http://pastebin.com/uhBGWC5e * Only thing changed is the task completion check (`while` -> `Task.WhenAll`). When awaiting an async operation inside of a Task, the Task status changes to `RanToCompletion` even though, the Task is still running. Now, let's see the setup: ``` // Start async. Task t1 = Task.Factory.StartNew(Accept, s1); Task t2 = Task.Factory.StartNew(Accept, s1); Task.WhenAll(t1, t2).Wait(); ``` The `Accept` method: ``` public static async void Accept(object state) { TcpListenerEx server = (TcpListenerEx) state; IPEndPoint endPoint = server.LocalEndpoint as IPEndPoint; Log("Accepting clients on {0}", endPoint); while (true) { var client = server.AcceptTcpClientAsync(); if (client == null) { Log("Null error on accept"); break; } TcpClient connected = (TcpClient) client; servers[server].Add(connected); bool stop = await Task<Task<bool>>.Factory.StartNew(Listen, connected).Unwrap(); if (stop == true) { break; } } // Stop the server. server.Stop(); Log("Stoppped {0}", endPoint); } ``` Because of TaskStatus changing to RanToCompletion, the `Task.WhenAll().Wait()` call marks itself finished fairly quickly, resulting in program to be executed further, eventually - terminated. But, the `Accept` task, in theory, should never stop, it's listening for connections until explicitly stopped. What is the problem here that's causing the Task to be marked as `RanToCompletion` prematurely?

Original source