C# 在继续之前等待来自所有线程的信号

标签 c# multithreading synchronization

我正在编写一个C#程序,其中涉及多线程和多个线程之间的同步。线程都需要独立执行一些迭代工作,并且某个线程完成指定次数的迭代后,必须等待其他线程出现。当它们全部完成给定次数的迭代并获得一些中间结果后,它们应该做一些同步工作,然后再次继续执行,直到到达另一个同步点,依此类推。

这是我实现这一目标的尝试(线程应该在一次迭代后暂停,然后等待其他迭代):

int nThreads = Environment.ProcessorCount;
Thread[] threads = new Thread[nThreads];

ManualResetEvent[] manualResetEvents = new ManualResetEvent[nThreads];
for (int i = 0; i < nThreads; i++)
{
    manualResetEvents[i] = new ManualResetEvent(false);
}

int nSteps = 5;
Random rnd = new Random();
for (int i = 0; i < nThreads; i++)
{
    int idx = i;
    threads[i] = new Thread(delegate ()
    {
        int cStep = nSteps;

        while (cStep > 0)
        {
            manualResetEvents[idx].Reset();
            Console.Write("\nThread {0} working... cStep = {1}\n", idx, cStep);

            Thread.Sleep(rnd.Next(1000));

            manualResetEvents[idx].Set();
            Console.WriteLine("\nThread {0} work done. Waiting Others...cStep = {1}\n", idx, cStep);

            WaitHandle.WaitAll(manualResetEvents);
            cStep--;
        }

    });
}

for (int i = 0; i < nThreads; i++)
{
    threads[i].Start();

}

for (int i = 0; i < nThreads; i++)
{
    threads[i].Join();
}

但是上面的代码似乎不起作用,因为没有任何线程出于某种原因等待所有其他线程执行一次迭代。我想我误解了 ManualResetEvent 的目的或以错误的方式使用它,你有什么建议?

最佳答案

您的代码很容易出现竞争条件。所有线程完成第一次迭代后,所有事件仍处于设置状态;如果单个线程在其他线程重置其事件之前运行循环,它将看到其他事件仍然设置,并提前停止等待。

有很多方法可以解决此错误,但最适合您的解决方案是 System.Threading.Barrier (另请参阅 Threading objects and features 以及有关 Barrier 的部分)。它是专门为这种情况而设计的,您希望多个线程通过多步骤算法并行工作。

关于C# 在继续之前等待来自所有线程的信号,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41138562/

相关文章:

Java方法同步使用不当?

c# - 同步集合 InvalidOperationException/System.ArgumentException

c - 使用互斥体的 Pthread 同步未正确同步单词

c# - 按下按钮时不激活窗口

c# - 画笔算法/颜色褪色模式 - 需要建议

c# - Windows 7 动画鼠标拖动事件

用于带有 GSM 调制解调器 rxtx 的 IVRS 的 Java 多线程(播放语音文件使事件监听器停止工作)

java - Executor 和 PriorityBlockingQueue 上的 ASyncTask

c# - 套接字在第一次接收后停止

bash - BASH中的多线程变量创建