所以我不能理解这里的概念。我有一个使用Parallel类和Foreach方法的方法。但我不明白的是,它是否创建新线程,以便它可以更快地运行该功能?
我们以此为例。我做一个正常的foreach循环。
private static void DoSimpleWork()
{
foreach (var item in collection)
{
//DoWork();
}
}
它将做的是,它将采取列表中的第一项,分配方法DoWork();到它并等到它完成。简单,朴实,有效。
现在..有三种情况我很好奇如果我这样做。
Parallel.ForEach(stringList, simpleString =>
{
DoMagic(simpleString);
});
将Foreach拆分为4块大块吗?所以我认为正在发生的是它需要列表中的前4行,将每个字符串分配给每个“线程”(假设并行创建4个虚拟线程)完成工作,然后从该列表中的下一个4开始?如果这是错的,请纠正我,我真的想了解这是如何工作的。
然后我们有了这个。这基本上是相同的,但有一个新的参数
Parallel.ForEach(stringList, new ParallelOptions() { MaxDegreeOfParallelism = 32 }, simpleString =>
{
DoMagic(simpleString);
});
我很好奇的是这个
new ParallelOptions() { MaxDegreeOfParallelism = 32 }
这是否意味着它将从该列表中获取前32个字符串(如果列表中有许多字符串)然后执行与我上面讨论的相同的事情?
而对于最后一个。
Task.Factory.StartNew(() =>
{
Parallel.ForEach(stringList, simpleString =>
{
DoMagic(simpleString);
});
});
这会创建一个新任务,将每个“块”分配给它自己的任务吗?
不要将异步代码与并行混合。任务是用于异步操作 - 查询数据库,读取文件,等待一些相对计算成本低廉的操作,以便您的UI不会被阻止和无响应。
平行是不同的。这是为1)多核系统和2)计算密集型操作而设计的。我不会详细介绍它是如何工作的,可以在MS文档中找到这种信息。简而言之,Parallel.For很可能会让自己决定究竟何时以及如何运行。它可能违反你的参数,即MaxDegreeOfParallelism或其他一些。整个想法是提供最佳的并行化,从而尽快完成您的操作。
Parallel.ForEach
执行相当于C#foreach循环,但每次迭代并行执行而不是顺序执行。没有排序,它取决于操作系统是否可以找到可用的线程,如果它将执行
MaxDegreeOfParallelism
默认情况下,For和ForEach将使用OS提供的线程数,因此从默认值更改MaxDegreeOfParallelism仅限制应用程序将使用多少并发任务。
您通常不需要修改此参数,但可以选择在高级方案中更改它:
当你需要对长期运行的计算绑定任务进行细粒度控制时,通常会使用Task.StartNew
,就像@СергейБоголюбов所提到的那样,不要混淆它们
它创建一个新任务,该任务将异步创建线程以运行for循环
你可能会发现这本电子书很有用:http://www.albahari.com/threading/#_Introduction
工作然后从该列表中的下一个4开始?
这取决于机器的硬件以及机器核心与CPU正在处理的其他进程/应用程序的繁忙程度
这是否意味着它将从该列表中获取前32个字符串(如果列表中有许多字符串),然后执行与上面讨论的相同的操作?
不,不能保证它会占用前32,可能会更少。每次执行相同的代码时都会有所不同
Task.Factory.StartNew创建一个新任务,但它不会像您期望的那样为每个块创建一个新任务。
将Parallel.ForEach放入新任务中将无助于您进一步缩短并行任务本身所需的时间。