【问题标题】:How do I write a C# Parallel.ForEach loop where during one part of the code, only one thread can be active at a time?如何编写一个 C# Parallel.ForEach 循环,其中在一部分代码中,一次只能激活一个线程?
【发布时间】:2021-12-30 20:51:37
【问题描述】:

不确定这是否可能没有大量开销,但我想我会问。

这是当前进程:

Parallel loop over locations
    Sequential Loop over SQL load operations for each location

这工作得很好,但如果同时执行超过 1 个线程,则一个过程往往会死锁。

是否有可能确保一旦死锁过程运行,所有其他线程在尝试执行相同的过程时都等待直到它完成?

我感觉涉及到锁定,但我没有做足够的事情来确定。

【问题讨论】:

  • 你试试锁吗?
  • 您可以使用lock 来确保一次只有一个线程可以执行某些操作。听起来很奇怪,好像它会破坏并行执行的目的。
  • 或者换个角度:你能弄清楚为什么程序会锁定并修复它吗?
  • 嗯,我会尝试使用锁,看看是否能满足我的需要。被调用的过程相对复杂,我可以理解它为什么会死锁。不幸的是,优化这将是一项繁重的工作。

标签: c# multithreading loops parallel-processing locking


【解决方案1】:

lock 命令满足了我的需求。

这是我如何解决它的精简版:

// This is a static variable in my main Program class
private static readonly object processLock = new object();

// This is within my processing method
Parallel.ForEach(Stores, new ParallelOptions() { MaxDegreeOfParallelism = maxdop }, store =>
{
    foreach (var sequenceFeed in Sequences.OrderBy(x => x.SequenceOrder))
    {                    
        if (sequenceFeed.Identifier == "UPC") // UPC deadlocks due to pricing code, so lock for single threaded execution
        {
            lock (processLock)
            {
                feed.Process();
            }
        }
        else
            feed.Process();
    }              
});

感谢 cmets 中的@Scott Hannen 提供指导。

【讨论】:

    【解决方案2】:
     Parallel loop over locations
       Sequential Loop over SQL load operations for each location
    

    我发现动态改变并行运行的线程数量的唯一方法是使用任务和SemaphoreSlim 逐渐增加运行的线程数量。然而,这不是你要找的。但是,根据您对要并行运行的过程的描述,您表明您正在从 SQL 加载数据。这表明您应该问的问题是为什么您的查询会死锁。如果您使用的是 SQL Server,那么我建议您查看此链接,Locking and Blocking in SQL Server 由 Brent Ozar 提供。当我遇到死锁问题时,我发现这个和他网站上的其他资源非常有用。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-10-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多