简体   繁体   English

为什么 Task.WhenAll 不起作用?

[英]Why isn't Task.WhenAll working?

Here's some code I'm working with, that fires of three tasks.这是我正在使用的一些代码,它触发了三个任务。 My Stop is called, and from the output, it looks as though the tasks finish after Stop returns, which isn't what I'd expect.我的 Stop 被调用,从输出来看,任务似乎Stop 返回完成,这不是我所期望的。

This is Visual Studio 2013 with .NET 4.5.1这是带有 .NET 4.5.1 的 Visual Studio 2013

I tried the same using AutoResetEvent which worked as expected.我使用 AutoResetEvent 尝试了同样的方法,它按预期工作。

Here's the output from this:这是输出:

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

What I'd expect to see is:我希望看到的是:

First done
Second done
Third done
All done!

Here's the code (I even added locking around the Console output, but it made no difference):这是代码(我什至在控制台输出周围添加了锁定,但没有任何区别):

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);
        }
    }
}

Because you're not waiting for Stop method to finish.因为您不是在等待Stop方法完成。 You can't wait for an async void method.您不能等待异步 void 方法。 You need return a Task, so that the caller can wait/await for it to complete.您需要返回一个任务,以便调用者可以等待/等待它完成。

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

    return Task.WhenAll(tasks);
}

Then you can call Stop().Wait();然后你可以调用Stop().Wait(); instead of Stop .而不是Stop That will wait for WhenAll to complete.这将等待WhenAll完成。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM