C# 帕拉勒·弗雷奇不适合我

C# 帕拉勒·弗雷奇不适合我,c#,parallel-processing,parallel.foreach,C#,Parallel Processing,Parallel.foreach,我对一些代码使用了Parallel.ForEach,但它给出的结果与非并行代码不同。因此,出于诊断目的,我确实使用lock关键字包装了整个代码: var someArray = new double[123]; var syncObject = new Object(); Parallel.ForEach (windows, (win) => { lock (syncObject) // now it should execute sequentially? {

我对一些代码使用了
Parallel.ForEach
,但它给出的结果与非并行代码不同。因此,出于诊断目的,我确实使用
lock
关键字包装了整个代码:

var someArray = new double[123];
var syncObject = new Object();

Parallel.ForEach (windows, (win) =>
{
    lock (syncObject) // now it should execute sequentially?
    {
          // do something with someArray
    }
});
我以为锁会使它非并行,但我仍然得到问题。 我认为它的作用与:

windows.ToList().ForEach ( (win) =>
{
    // do something with someArray
});

在这种情况下,锁怎么可能不会终止并行性?

将代码重写为PLINQ,它相当于您的
并行。ForEach

        windows
            .AsParallel()
            .ForAll((win) =>
        {
            //DoSomething
        });
然后将带有degreeofparallelism(1)的
添加到“KILL”并行性中。因此,您可以看到bug是来自并行运行的线程还是来自其他方面

        windows
            .AsParallel()
            .WithDegreeOfParallelism(1)
            .ForAll((win) =>
        {
            //DoSomething
        });

关于粘贴的代码段的代码的串行执行,您的假设是不正确的

Parallel.ForEach (windows, (win) =>
{
    lock (syncObject) // now it should execute sequentially?
    {
          // do something with someArray
    }
});
您放在那里的
lock
确保每次只有一个线程可以访问代码的这个特定关键部分(包含在
lock(syncObject){}
中的代码),但这并不意味着语句本身将按顺序执行

将Parallel.ForEach替换为ThreadPool,这可能会使您更容易理解:

foreach(var item in list)
{
      ThreadPool.QueueUserWorkItem(i =>
                                       {
                                           lock (syncObject)
                                           {
                                               // do something with i here
                                           }
                                       }, item);
 }
这两个代码段或多或少是等效的。正如您所看到的,您首先为列表中的每个项目启动一个线程,然后在线程内部获得锁,该锁将确保没有其他线程可以访问封闭的关键部分。但是,这不能保证它们是按顺序完成的,并且顺序是存在的他被激怒了

线程池中线程的执行顺序不受您的控制,因此,使用线程池无法保证任何顺序(至少,不是传统意义上的)

现在让我们看看这个例子,希望它能让事情变得更清楚:

var syncObject = new Object();
var list = new List<int>();
for(int i=0;i<20;i++)
{
    list.Add(i);
}

Parallel.ForEach(list, item =>
{
    Console.WriteLine(item + " waiting to be executed on " + Thread.CurrentThread.ManagedThreadId);
    lock (syncObject) // now it should execute sequentially?
    {
        Console.WriteLine(item + " executing on " + Thread.CurrentThread.ManagedThreadId);
                Thread.Sleep(100);

     }
 });

如您所见,可能有多个线程等待进入关键部分,但在任何给定时间只有一个线程将执行
锁中的语句。但是由于线程池线程管理和计划。

这将强制代码序列化。显然,你的问题不在于代码的并行化,而在于其他方面。在不知道你在做什么,或者没有复制示例的情况下,我们不可能说你做错了什么。序列化了吗?你能告诉我更多吗?我现在就回家,第二天我会添加mo如果可能的话,我会提供详细信息,因为我有很多代码。不,我们不能告诉你更多,你有一些代码即使在没有并行化的情况下也无法工作。它可能有各种各样的问题,但同时运行的迭代不在其中。这意味着一次只能运行一个循环,但顺序可能不同nt。很可能你的代码取决于顺序。@juharr:你说得对,问题解决了。在新鲜空气中呼吸了5分钟后,我解决了我的问题。这正是你所说的。任务或多或少是以随机顺序执行的。我在计算浮点数。所以通常使用浮点数:A+B+C!=A+C+B(如果C!=B).这个问题给了我计算上的微小差异。谢谢你的详细帖子。
0 waiting to be executed on 1
0 executing on 1
2 waiting to be executed on 4
4 waiting to be executed on 6
10 waiting to be executed on 9
12 waiting to be executed on 5
8 waiting to be executed on 10
16 waiting to be executed on 7
6 waiting to be executed on 8
14 waiting to be executed on 3
1 waiting to be executed on 11
2 executing on 4
10 executing on 9
3 waiting to be executed on 4
11 waiting to be executed on 9
16 executing on 7
14 executing on 3
17 waiting to be executed on 7
15 waiting to be executed on 3
8 executing on 10
9 waiting to be executed on 10
4 executing on 6
12 executing on 5
5 waiting to be executed on 6
6 executing on 8
13 waiting to be executed on 5
1 executing on 1
7 waiting to be executed on 8
3 executing on 4
18 waiting to be executed on 1
11 executing on 9
17 executing on 7
15 executing on 3
9 executing on 10
5 executing on 6
13 executing on 5
7 executing on 8
18 executing on 1
19 waiting to be executed on 1
19 executing on 1