【发布时间】:2019-09-08 02:28:15
【问题描述】:
这是我正在运行的伪代码:
变体 #1:
List<Task> tasks = new List<Task>();
foreach (...)
{
Task task = Task.Run(() =>
{
doWork();
});
tasks.Add(task);
}
Task.WhenAll(tasks.AsParallel()).ContinueWith((t) =>
{
// process results/handle errors
...
});
变体 #2:
List<Task> tasks = new List<Task>();
foreach (...)
{
Task task = Task.Run(() =>
{
doWork();
});
tasks.Add(task);
}
Task.WhenAll(tasks.AsParallel()).Wait();
// process results/handle errors
...
我的问题是,为什么调用doWork 的方式在#1 和#2 之间出现根本不同?这是设计使然,我只是不明白这应该如何工作?
我(显然失败)的理解/假设是,doWork 将以多线程/异步方式调用,如果可用则并行,两种场景,唯一的区别是调用代码会以不同的方式等待完成。但是任务的实际执行方式是相同的,因为它们的计划/“运行”方式相同。
但从调试两个版本的代码后我可以看出,变体 #1 导致 doWork 以真正的并行/完全多线程方式调用,而变体 #2 似乎表现得像一个单一的-每个任务的线程化、顺序执行。
我错过了什么?
【问题讨论】:
-
首先摆脱
AsParallel,这不属于这里。WhenAll采用IEnumerable或数组。然后看看这个:stackoverflow.com/a/41953073/224370 -
如何等待
Task.WhenAll()在变体 #1 中完成?我知道ContinueWith()只会在那时执行,但是您如何阻止您的应用程序/方法退出? -
@IanMercer - 感谢您对其他答案的引用;关于它在同一线程上运行(同步时)的部分实际上回答了我的问题。
Wait的文档只是说“等待任务完成执行”,并没有提及单线程与多线程的任何内容...... -
@sellotape,我根本没有在那儿等,我已经将所有结果处理代码移到
ContinueWith处理程序的主体中。
标签: c# multithreading plinq