【问题标题】:Problems with waiting for the threads to end等待线程结束的问题
【发布时间】:2013-02-03 21:10:50
【问题描述】:

我正在做一些 C# 线程。启动线程并将数据传输给它们没有问题,但我在等待它们结束时遇到了问题。

我的代码如下所示。我正在使用Join() 等待线程结束,但由于某种原因我的代码不起作用。

尽管在所有活动线程上调用了Join(),但主线程(即 for 循环)并未被阻塞。

知道我做错了什么吗?

List<Thread> calculationThreads = new List<Thread>();

foreach (string calculation in calculations)
{
    if (calculationThreads.Count < 5)
    {
        Thread calculationThread = new Thread(DoCalculation);
        calculationThreads.Add(calculationThread);

        calculationThread.Start(threadData);
    }
    else
    {
        // Wait for the threads to complete
        foreach (Thread calculationThread in calculationThreads)
        {
            calculationThread.Join();
        }
    }   
}

【问题讨论】:

  • 确定计算线程没有全部终止?
  • 您是否考虑过使用任务并行库来处理您的线程,而不是像这样明确地执行它?很多有用的方法让你的生活更轻松:msdn.microsoft.com/en-us/library/dd537609.aspx
  • 我认为你应该在加入后从 CalculationThreads 集合中删除线程。
  • 您确定它根本没有阻塞吗?在我看来,它会阻止前 5 次计算,但由于您永远不会从列表中删除已完成的计算,之后它就会直接通过。
  • 为什么你的代码“不起作用”?

标签: c# multithreading join


【解决方案1】:

第一个问题是您对else 案例的处理。如果已经有五个线程,代码将等待线程完成,但它试图添加的任务永远不会添加。它只会丢弃该任务并继续下一个任务。

第二个问题是您没有从列表中删除任何线程,因此一旦达到五个线程,它将永远等待。如果第一个问题没有放弃其余任务,您的程序就会锁定。

此外,在继续工作之前等待所有五个线程都完成是在浪费处理时间,但这是一个较小的问题。

【讨论】:

  • 处理时间的浪费是的,但是如果线程产生的数据中存在任何依赖关系,则序列应该在for循环之后等待。
  • @StianStandahl:是的,当最后一个任务被处理到一个线程时,您必须等待所有线程完成才能使用结果,这是不可避免的。然而,当前的代码会将任务分成五个一组,并为每个组带来浪费。
【解决方案2】:

我会采用一些方法,只计算我启动了多少线程,并在每个线程结束时减少计数器。

然后在循环的开始你可以有

while(counter >= 5)
{
//Wait
}

【讨论】:

    【解决方案3】:

    你可以有一个等待所有线程结束的while循环。

    List<Thread> calculationThreads = new List<Thread>();
    
    foreach (string calculation in calculations)
    {
        if (calculationThreads.Count < 5)
        {
            Thread calculationThread = new Thread(DoCalculation);
            calculationThreads.Add(calculationThread);
    
            calculationThread.Start(threadData);
        }
        else
        {
            // Wait for the threads to complete
            while(calculationThread.Any(x => x.IsAlive)){}
            // Clearing the list
            calculationThread.Clear();
        }   
    }
    

    如果你想在 for 循环之后保留线程,你应该有另一个列表来存储线程。

    【讨论】:

    • 哎哟。你绝对不应该有一个繁忙的循环等待线程完成。
    • 我知道。那里应该有一个超时功能;)
    【解决方案4】:

    您为该方法提供了多少计算?

    阅读代码,如果您提供 4 个计算,您将启动 4 个线程,但从未真正转到执行 thread.Join() 的代码。

    将 thread.join 循环移到 if else 语句之外。

    List<Thread> calculationThreads = new List<Thread>();
    
        foreach (string calculation in calculations)
        {
            if (calculationThreads.Count < 5)
            {
                Thread calculationThread = new Thread(DoCalculation);
                calculationThreads.Add(calculationThread);
    
                calculationThread.Start(threadData);
            }
    
        }
        foreach (Thread calculationThread in calculationThreads)
        {
            calculationThread.Join();
        }
    

    【讨论】:

      猜你喜欢
      • 2012-07-13
      • 2021-11-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-12-03
      • 1970-01-01
      相关资源
      最近更新 更多