C# 如何按顺序执行Parallel.For循环和Parallel.ForEach循环

C# 如何按顺序执行Parallel.For循环和Parallel.ForEach循环,c#,task-parallel-library,C#,Task Parallel Library,我知道如何编写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.CurrentThr

我知道如何编写
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);      
});
但这两个代码示例的问题是循环没有按顺序执行。如何使它们按顺序执行?我从别人那里听说,你必须锁定一个物体,然后这是可能的。我试过搜索,试过很多代码示例,但没有用

此外,我想知道按顺序执行的并行循环的性能是否会更低?如果没有,为什么没有?因为锁定,在我看来会导致延迟


至于我对并行编程的理解,调度器在运行时进行调度。有人能告诉我们.NETIDE使用什么算法/策略来调度多个核心上的代码吗?它的好处是由内而外的并行编程。

让线程同时并行和顺序运行对您来说真的没有意义

如果
线程3
线程1
之前完成,会发生什么情况?如果要阻止
线程3
并使其等待
线程1
完成,那么使用线程有什么意义

但是,如果您希望按顺序完成批处理,这是可能的,但仍然不理想

我的意思是,如果您有一个运行两个线程的列表
[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);
    }
}
void Main()
{
var项目=可枚举范围(1100);
const int numThreads=4;
foreach(items.batch中的var批处理(numThreads))
{
变量线程=批处理。选择(项=>{
返回新线程(()=>Console.WriteLine(item));
}).ToList();
threads.ForEach(t=>t.Start());
threads.ForEach(t=>t.Join());
}
}
公共静态类Ext
{
公共静态IEnumerable批(
此IEnumerable源(整数大小)
{
TSource[]bucket=null;
var计数=0;
foreach(源中的var项)
{
if(bucket==null)
bucket=新的TSource[size];
桶[count++]=物料;
如果(计数!=大小)
继续;
回程铲斗;
bucket=null;
计数=0;
}
if(bucket!=null&&count>0)
产量返回桶。取(计数);
}
}

批处理扩展方法取自

让线程并行和顺序运行对您来说并没有什么意义

如果
线程3
线程1
之前完成,会发生什么情况?如果要阻止
线程3
并使其等待
线程1
完成,那么使用线程有什么意义

但是,如果您希望按顺序完成批处理,这是可能的,但仍然不理想

我的意思是,如果您有一个运行两个线程的列表
[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);
    }
}
void Main()
{
var项目=可枚举范围(1100);
const int numThreads=4;
foreach(items.batch中的var批处理(numThreads))
{
变量线程=批处理。选择(项=>{
返回新线程(()=>Console.WriteLine(item));
}).ToList();
threads.ForEach(t=>t.Start());
threads.ForEach(t=>t.Join());
}
}
公共静态类Ext
{
公共静态IEnumerable批(
此IEnumerable源(整数大小)
{
TSource[]bucket=null;
var计数=0;
foreach(源中的var项)
{
if(bucket==null)
bucket=新的TSource[size];
桶[count++]=物料;
如果(计数!=大小)
继续;
回程铲斗;
bucket=null;
计数=0;
}
if(bucket!=null&&count>0)
产量返回桶。取(计数);
}
}

批处理扩展方法取自

,它们将按顺序执行,首先是For,然后是ForEach。但它们在各自范围内的结果不能保证是按顺序执行的。如果要按顺序执行,请使用
for
foreach
,对集合进行排序的任何先决条件都会降低它在以
并行运行时的性能,甚至可能比按顺序执行的顺序循环更慢,先为后为。但是,它们在各自范围内的结果不能保证是按顺序执行的。如果希望按顺序执行,请使用
for
foreach
,对集合排序的任何先决条件都会降低它在
并行运行时的性能,甚至可能比顺序循环慢