线程障碍问题 - PulseAll没有到达所有线程

时间:2014-05-08 12:28:27

标签: c# multithreading parallel-processing barrier

我有一个并行算法,我遇到了一些障碍问题。在你们尖叫“搜索”之前,我可以说我已经查看了可用的帖子和链接,我已经按照说明找到了Monitor.Wait和Monitor.PulseAll的屏障,但我的问题是除了最后一个创建的所有线程PulseAll从我的主线程到达(并启动)。以下是代码的基本布局:

public static object signal = new object(); //This one is located as class variable, not in the method

public void RunAlgorithm(List<City> cities){
    List<Thread> localThreads = new List<Thread>();
    object[] temp = //some parameters here
    for(int i = 0; i < numOfCitiesToCheck; i++){
        Thread newThread = new Thread((o) => DoWork(o as object[]));
        newThread.IsBackground = true; 
        newThread.Priority = ThreadPriority.AboveNormal;
        newThread.Start(temp as object);
        localThreads.Add(newThread);
    }

    //All threads initiated, now we pulse all
    lock(signal){
        Monitor.PulseAll(signal); 
    }
    int counter = 0;
    while(true){
        if(counter == localThreads.Count){ break; }
        localThreads[counter].Join();
        counter++;
    }
}

这是由主线程完成的(删除了一些不必要的部分)并且如前所述,主线程将始终卡在列表中最后一个线程的Join()中。 这就是线程的方法:

private void DoWork(object[] arguments){
    lock(signal){
        Monitor.Wait(signal);
    }
    GoDoWork(arguments); 
}

我可以使用这种类型的信令吗?我想要的是让主线程同时发出所有线程的信号,以便它们同时启动。我希望它们能够同时启动,以便尽可能地保持平行(我测量算法的运行时间和其他一些事情)。我的屏障或代码中是否有任何部分存在缺陷(我的意思是屏障)?我尝试运行一个线程较少的实例,它仍然卡在最后一个,我不知道为什么。我通过VS调试确认最后一个线程正在休眠(所有其他线程都是!isAlive,而最后一个线程是isAlive = true)。 任何帮助赞赏!

1 个答案:

答案 0 :(得分:1)

我设法使用Barrier类来解决它。非常感谢Damien_The_Unbeliever!还是不敢相信我之前没有听说过。

public Barrier barrier = new barrier(1); 

public void RunAlgorithm(List<City> cities){
    List<Thread> localThreads = new List<Thread>();
    object[] temp = //some parameters here
    for(int i = 0; i < numOfCitiesToCheck; i++){
        barrier.AddParticipant(); 
        Thread newThread = new Thread((o) => DoWork(o as object[]));
        newThread.IsBackground = true; 
        newThread.Priority = ThreadPriority.AboveNormal;
        newThread.Start(temp as object);
        localThreads.Add(newThread);
    }

    barrier.SignalAndWait(); 
    int counter = 0;
    while(true){
        if(counter == localThreads.Count){ break; }
        localThreads[counter].Join();
        counter++;
    }
}


private void DoWork(object[] arguments){
    barrier.SignalAndWait();
    GoDoWork(arguments); 
}