为什么不是Task.WhenAll工作?

时间:2015-10-07 08:41:49

标签: c# .net concurrency task

这是我正在使用的一些代码,即三个任务。我的Stop被调用,从输出中看,任务在 Stop返回后完成,这不是我所期望的。

这是带有.NET 4.5.1的Visual Studio 2013

我尝试使用AutoResetEvent,它按预期工作。

以下是此输出:

Three tasks without auto reset
Starting...
FIRST
SECOND
THIRD
Running...
FIRST
FIRST
FIRST
SECOND
FIRST
FIRST
THIRD
...
SECOND
FIRST
Stopping...
THIRD
All done!
First done
Second done
Third done

我期望看到的是:

First done
Second done
Third done
All done!

这是代码(我甚至在控制台输出周围添加了锁定,但没有区别):

public class ThreeTasksWithoutAutoResetEvent
{
    private CancellationTokenSource cancellation;

    private Task[] tasks;

    private object obj = new object();

    public ThreeTasksWithoutAutoResetEvent()
    {
        Console.WriteLine("Three tasks without auto reset");

        cancellation = new CancellationTokenSource();

        tasks = new Task[3];

        Message("Starting...");

        Start();

        Message("Running...");

        Thread.Sleep(3000);

        Message("Stopping...");

        Stop();

        Message("All done!");
    }

    private void Start()
    {
        tasks[0] = this.First(cancellation.Token);
        tasks[1] = this.Second(cancellation.Token);
        tasks[2] = this.Third(cancellation.Token);
    }

    private async void Stop()
    {
        cancellation.Cancel();

        await Task.WhenAll(tasks);
    }

    private async Task First(CancellationToken token)
    {
        await Task.Run(
            () =>
            {
                while (!token.IsCancellationRequested)
                {
                    Message("FIRST");
                    Thread.Sleep(100);
                }

                Message("First done");
            }, token);
    }

    private async Task Second(CancellationToken token)
    {
        await Task.Run(
            () =>
            {
                while (!token.IsCancellationRequested)
                {
                    Message("SECOND");
                    Thread.Sleep(300);
                }

                Message("Second done");
            }, token);
    }

    private async Task Third(CancellationToken token)
    {
        await Task.Run(
            () =>
            {
                while (!token.IsCancellationRequested)
                {
                    Message("THIRD");
                    Thread.Sleep(500);
                }

                Message("Third done");
            }, token);
    }

    private void Message(string message)
    {
        lock (obj)
        {
            Console.WriteLine(message);
        }
    }
}

1 个答案:

答案 0 :(得分:1)

因为您没有等待Stop方法完成。您不能等待异步void方法。您需要返回一个Task,以便调用者可以等待/等待它完成。

private Task Stop()
{
    cancellation.Cancel();

    return Task.WhenAll(tasks);
}

然后,您可以拨打Stop().Wait();而不是Stop。这将等待WhenAll完成。