为什么 Task.WhenAll 不工作?
Why isn't Task.WhenAll working?
这是我正在使用的一些代码,它触发了三个任务。我的 Stop 被调用,从输出来看,任务似乎在 after Stop returns 完成,这不是我所期望的。
这是 Visual Studio 2013 年的 .NET 4.5.1
我使用 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);
}
}
}
因为您没有等待 Stop
方法完成。您不能等待 async void 方法。您需要 return 个任务,以便调用者可以 wait/await 完成它。
private Task Stop()
{
cancellation.Cancel();
return Task.WhenAll(tasks);
}
那么你可以调用 Stop().Wait();
而不是 Stop
。这将等待 WhenAll
完成。
这是我正在使用的一些代码,它触发了三个任务。我的 Stop 被调用,从输出来看,任务似乎在 after Stop returns 完成,这不是我所期望的。
这是 Visual Studio 2013 年的 .NET 4.5.1
我使用 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);
}
}
}
因为您没有等待 Stop
方法完成。您不能等待 async void 方法。您需要 return 个任务,以便调用者可以 wait/await 完成它。
private Task Stop()
{
cancellation.Cancel();
return Task.WhenAll(tasks);
}
那么你可以调用 Stop().Wait();
而不是 Stop
。这将等待 WhenAll
完成。