Task.Factory.StartNew ignores Task.WaitAll
本文关键字:Task WaitAll ignores StartNew Factory | 更新日期: 2023-09-27 17:57:19
我在使用Task.Factory.StartNew和Task.WaitAll时遇到了一些问题。任务确实按预期启动,但看起来它只是忽略了 Task.WaitAll,因为在单击我的按钮(这是此代码所在的事件)后,MessageBox 已经弹出。
List<Task> tasks = new List<Task>();
if (plugin.UseProxy)
{
foreach (var item in combo)
{
Task.Factory.StartNew(() =>
{
// Some code
}).ContinueWith((t) =>
{
tasks.Add(t);
pbProgress.Value++;
}, TaskScheduler.FromCurrentSynchronizationContext());
}
}
else
{
foreach (var item in combo)
{
Task.Factory.StartNew(() =>
{
// Some code
}).ContinueWith((t) =>
{
tasks.Add(t);
pbProgress.Value++;
}, TaskScheduler.FromCurrentSynchronizationContext());
}
}
Task.WaitAll(tasks.ToArray());
MessageBox.Show("Hello");
只有在任务完成后,您才能将任务添加到列表中。 ContinueWith
任务完成后执行。因此,Task.WaitAll
正在等待一个空的任务列表。
所以你可以这样做:
Task task = Task.StartNew(() =>
{
// Some code
}).ContinueWith((t) =>
{
pbProgress.Value++;
}, TaskScheduler.FromCurrentSynchronizationContext());
tasks.Add(task);
只有在线程通过StartNew
启动后,tasks
列表才会获得添加到其中的项目。您遇到的问题是您在将项目添加到集合之前点击了Task.WaitAll(tasks.ToArray());
。您需要将项目添加到创建它们的线程中的集合中,而不是在继续,
var newTask = Task.Factory.StartNew(() =>
{
// Some code
});
tasks.Add(newTask);
newTask.ContinueWith((t) =>
{
pbProgress.Value++;
}, TaskScheduler.FromCurrentSynchronizationContext());
但是,您的代码也有其他问题。您永远不会将TaskSchedueller
传递给工厂,否则很容易意外地在 UI 线程上启动线程。此外,我假设此代码在 UI 线程上运行,您的Task.WaitAll
将阻止 UI 线程。如果其中一个StartNew
线程最终位于 UI 线程上,这可能会导致死锁。