【问题标题】:C# .Net 4.0 Console App - how to stay alive until all threads complete? [duplicate]C# .Net 4.0 控制台应用程序 - 如何在所有线程完成之前保持活动状态? [复制]
【发布时间】:2011-05-05 18:30:42
【问题描述】:

可能重复:
C#: Waiting for all threads to complete

我有一个控制台应用程序,它产生一些线程然后退出。每个线程大约需要 20 秒才能完成。似乎控制台应用程序正在生成线程,然后在线程有机会完成之前退出。

我如何告诉控制台应用在它产生的所有线程都完成之前不要退出?

【问题讨论】:

  • 很好的答案集。 @JohnEgbert - 线程是在循环中产生的,所以你的解决方案正是我想要的。虽然我确信其他人将从提供的解决方案中受益。

标签: c# multithreading .net-4.0 console-application


【解决方案1】:

您可以使用CountDownEvent

using System;
using System.Collections.Generic;
using System.Threading;

namespace ConsoleApplication1
{
    class Program
    {
        static CountdownEvent countdown;

        static void Main(string[] args)
        {
            countdown = new CountdownEvent(1);
            for (int i = 1; i < 5; i++)
            {
                countdown.AddCount(); //add a count for each (BEFORE starting thread .. Thanks, Brian!)
                //do stuff to start background thread
            }
            countdown.Signal(); //subtract your initial count
            countdown.Wait(); //wait until countdown reaches zero
            //done!
        }

        static void backgroundwork()
        {
            //work
            countdown.Signal(); //signal this thread's completion (subtract one from count)
        }
    }
}

【讨论】:

  • 我经常使用这种模式。它工作得很好。请注意,AddCount 应该在启动线程之前真正发生,否则如果第一个线程在调用 AddCount 之前完成,可能会导致事件过早发出信号。
  • 从未想过,但它可能会发生。很少见,但排除故障非常烦人。
  • 哈..是的,很少有人轻描淡写,尤其是当线程正在做任何有用的工作时。但是,伙计,这肯定是一个需要排除故障的地狱!
【解决方案2】:

线程是为循环而产生的吗?如果是这样,Parallel.ForEach 会起作用:

ParallelOptions options = new ParallelOptions();
                    Parallel.ForEach(items, options, item=>
                    {
// Do Work here
                    });

【讨论】:

  • 如果您实际上不打算设置任何选项,我可能会选择不需要您传入ParallelOptions 的重载,并且完全省略第一行。
【解决方案3】:

只要 Thread 不是后台线程 (.IsBackground),应用程序就应该保持活动状态:

static void Main()
{
    Thread thread = new Thread(MoreStuff);
    thread.IsBackground = false;
    thread.Start();
    Console.WriteLine("Main thread exiting");
}
static void MoreStuff()
{
    Console.WriteLine("Second thread starting");
    Thread.Sleep(5000); // simulate work
    Console.WriteLine("Second thread exiting");
}

不需要其他任何东西。注意ThreadPool 将使用后台线程;问题可能是您在这里使用ThreadPool 吗?

注意:如果第二个线程实际上还没有从那里开始可能是一场小竞赛,它可能会提前退出;您可能想要控制线程开始

【讨论】:

    【解决方案4】:

    您可以使用Thread.Join 等待线程完成。

    【讨论】:

      【解决方案5】:

      你是如何启动线程的?这确实取决于,但如果您只是使用 Thread 类,则从主线程调用 yourThread[i].Join() 以确保所有线程都完成。

      查看Tasks and Task Factory 以比过去几年更干净地处理事情。

      【讨论】:

        【解决方案6】:

        在您启动的所有线程上调用Thread.Join()。这将阻塞当前线程,直到线程完成。

        【讨论】:

          【解决方案7】:

          您可能应该使用同步并等待任何生成的线程完成它们的工作,方法是通过调用 Thread.Join 或使用信号(例如,使用监视器或其他选项之一)阻塞主线程。

          或者,您可以通过设置 IsForeground 属性 (afaicr) 简单地使生成的线程作为前台线程运行。这将使应用程序保持活动状态,直到线程终止,但您仍然会看到控制台窗口在主线程退出时消失。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2018-08-19
            • 2017-10-12
            • 2012-11-20
            • 1970-01-01
            • 1970-01-01
            • 2011-02-04
            • 1970-01-01
            • 2017-04-10
            相关资源
            最近更新 更多