我知道如何编写Parallel.For
和Parallel.ForEach
循环。以下是两者的示例代码:
Parallel.For(0,10, (int i) = >
{
Console.Writeline(i);
});
Parallel.ForEach(fruits, fruit =>
{
Console.WriteLine("Fruit Name: {0}, Thread Id= {1}", fruit, Thread.CurrentThread.ManagedThreadId);
});
但这两个代码示例的问题是循环不按顺序执行。如何让它们按顺序执行?我从人们那里听说你必须锁定一个物体,然后才有可能。我试过搜索并尝试了很多代码示例但没有用。
此外,我想知道按顺序执行的并行循环的性能是否较小?如果不是,为什么不呢?因为锁定,会导致我拙见的延迟。
至于我对并行编程的理解,调度程序在运行时生成调度。任何人都可以告诉.NET IDE使用什么算法/策略来安排几个核心上的代码?其货物内部出于并行编程。
答案 0 :(得分:0)
让线程并行和按顺序运行并不合理。
如果Thread 3
在Thread 1
之前完成,会发生什么?如果你要阻止Thread 3
并让它等到Thread 1
完成,那么使用线程有什么意义呢?
但是,如果您希望按顺序完成批次,则可能但仍然不理想。
我的意思是,如果你有一个运行2个线程的列表[1,2,3,4,5,6,7,8,9,10]
,你可以确保在任何其他项之前处理1
和2
,所以上。要做到这一点,你可以使用这样的东西:
void Main()
{
var items = Enumerable.Range(1, 100);
const int numThreads = 4;
foreach(var batch in items.Batch(numThreads))
{
var threads = batch.Select(item => {
return new Thread(() => Console.WriteLine(item));
}).ToList();
threads.ForEach(t => t.Start());
threads.ForEach(t => t.Join());
}
}
public static class Ext
{
public static IEnumerable<IEnumerable<TSource>> Batch<TSource>(
this IEnumerable<TSource> source, int size)
{
TSource[] bucket = null;
var count = 0;
foreach (var item in source)
{
if (bucket == null)
bucket = new TSource[size];
bucket[count++] = item;
if (count != size)
continue;
yield return bucket;
bucket = null;
count = 0;
}
if (bucket != null && count > 0)
yield return bucket.Take(count);
}
}
批量扩展方法取自this answer