Task.WhenAll - 不等待子任务完成
Task.WhenAll - not waiting for child tasks to finish
我对 TPL 有一些疑问。
如您所见,我正在创建 2 个简单任务并将它们添加到列表中。
问题(预期行为)是任务 return 在 WorkMethodAsync
中点击 "await" 后立即执行,因此呈现 Task.WhenAll
无用。
有没有办法等待子任务完成?
我发现的唯一解决方法是伪装 WorkMethodAsync
是同步的。
private async void button1_Click(object sender, EventArgs e)
{
Tasks = new List<Task>();
var myTask1 = Task.Factory.StartNew(async () => await WorkMethodAsync(), CancellationToken.None, TaskCreationOptions.LongRunning, TaskScheduler.Default);
var myTask2 = Task.Factory.StartNew(async () => await WorkMethodAsync(), CancellationToken.None, TaskCreationOptions.LongRunning, TaskScheduler.Default);
Tasks.Add(myTask1);
Tasks.Add(myTask2);
await Task.WhenAll(Tasks.ToArray());
}
private async Task WorkMethodAsync()
{
while (true)
{
await Task.Delay(10000);
}
return;
}
问题是您使用的是 Task.Factory.StartNew
而不是 Task.Run
。
StartNew
是在 async-await 之前构建的,因此不能很好地支持它。在这种情况下,由于您的委托 return 是一个任务并且 StartNew
创建了一个任务,因此 return 值为 Task<Task>>
。您可以使用 Unwrap
来获取代表整个异步操作的任务:
Task<Task> myTask1 = Task.Factory.StartNew(async () => await WorkMethodAsync(), CancellationToken.None, TaskCreationOptions.LongRunning, TaskScheduler.Default);
Task<Task> myTask2 = Task.Factory.StartNew(async () => await WorkMethodAsync(), CancellationToken.None, TaskCreationOptions.LongRunning, TaskScheduler.Default);
Tasks.Add(myTask1.Unwrap());
Tasks.Add(myTask2.Unwrap());
但是,确实没有理由首先使用 Task.Factory.StartNew
,因为 TaskCreationOptions.LongRunning
对于异步方法没有意义(我的博客上有更多相关信息:LongRunning Is Useless For Task.Run With async-await)所以你可以只使用 Task.Run
:
var myTask1 = Task.Run(() => WorkMethodAsync());
var myTask2 = Task.Run(() => WorkMethodAsync());
我对 TPL 有一些疑问。
如您所见,我正在创建 2 个简单任务并将它们添加到列表中。
问题(预期行为)是任务 return 在 WorkMethodAsync
中点击 "await" 后立即执行,因此呈现 Task.WhenAll
无用。
有没有办法等待子任务完成?
我发现的唯一解决方法是伪装 WorkMethodAsync
是同步的。
private async void button1_Click(object sender, EventArgs e)
{
Tasks = new List<Task>();
var myTask1 = Task.Factory.StartNew(async () => await WorkMethodAsync(), CancellationToken.None, TaskCreationOptions.LongRunning, TaskScheduler.Default);
var myTask2 = Task.Factory.StartNew(async () => await WorkMethodAsync(), CancellationToken.None, TaskCreationOptions.LongRunning, TaskScheduler.Default);
Tasks.Add(myTask1);
Tasks.Add(myTask2);
await Task.WhenAll(Tasks.ToArray());
}
private async Task WorkMethodAsync()
{
while (true)
{
await Task.Delay(10000);
}
return;
}
问题是您使用的是 Task.Factory.StartNew
而不是 Task.Run
。
StartNew
是在 async-await 之前构建的,因此不能很好地支持它。在这种情况下,由于您的委托 return 是一个任务并且 StartNew
创建了一个任务,因此 return 值为 Task<Task>>
。您可以使用 Unwrap
来获取代表整个异步操作的任务:
Task<Task> myTask1 = Task.Factory.StartNew(async () => await WorkMethodAsync(), CancellationToken.None, TaskCreationOptions.LongRunning, TaskScheduler.Default);
Task<Task> myTask2 = Task.Factory.StartNew(async () => await WorkMethodAsync(), CancellationToken.None, TaskCreationOptions.LongRunning, TaskScheduler.Default);
Tasks.Add(myTask1.Unwrap());
Tasks.Add(myTask2.Unwrap());
但是,确实没有理由首先使用 Task.Factory.StartNew
,因为 TaskCreationOptions.LongRunning
对于异步方法没有意义(我的博客上有更多相关信息:LongRunning Is Useless For Task.Run With async-await)所以你可以只使用 Task.Run
:
var myTask1 = Task.Run(() => WorkMethodAsync());
var myTask2 = Task.Run(() => WorkMethodAsync());