4

生成されたスレッドが完全に終了するまでコンソール アプリが待機しない理由がわかりません。これは、問題のスレッドが独自の子スレッドを生成したり、System.Timer を含めたりするという事実に関連していると思います。

基本的なプログラムの流れは以下の通りです。Main は Simulator.Start メソッドに対して新しいスレッドを作成し、そのスレッドが終了するまで参加します。Simulator.Start は、Timer(実行時間を制限するために) 新しいスレッドを作成し、一連の子スレッドを作成/実行します。によってElapsedイベントが発生するとTimer、これは、シミュレータがすべての子スレッドを終了し、レポートを生成する必要があることを示します。問題は、すべての子スレッドが終了するとすぐにコンソール アプリが終了し、レポートを生成するコードが実行されないことです (以下の Simulator.Stop メソッドを参照)。

うまくいけば、いくつかの疑似コードが役立ちます:

public class Program
{
    private static Simulator _simulator;

    private static void Main(string[] args)
    {
        var options = new SimulationOptions();
        //check for valid options
        if (!Parser.Default.ParseArguments(args, options)) return;

        _simulator = new Simulator(options);

        var thread = new Thread(_simulator.Start) {IsBackground = false};
        thread.Start();
        thread.Join();
    }
}

public class Simulator
{
    private readonly SimulationOptions _options;
    private readonly List<Thread> _threads = new List<Thread>();
    private readonly List<Worker> _workers = new List<Worker>();
    private static Timer _timer;

    public Simulator(SimulationOptions options)
    {
        _options = options;
        StartTimer(_options.LengthOfTest);
    }

    private void StartTimer(int lengthOfTest)
    {
        _timer = new Timer {Interval = lengthOfTest*1000};
        _timer.Elapsed += Timer_Elapsed;
        _timer.Start();
    }

    private void Timer_Elapsed(object sender, ElapsedEventArgs e)
    {
        _timer.Stop();
        Stop();
    }

    public void Stop()
    {
        // Request that the worker thread stop itself:
        foreach (Worker worker in _workers)
        {
            worker.RequestStop();
        }

        GenerateReport(); //<-- this code never gets executed
    }

    private XDocument GenerateReport()
    {
        //build an awesome report
    }

    public void Start()
    {
        _threads.Clear();
        _workers.Clear();
        for (int i = 0; i < _options.NumberOfClients; i++)
        {
            _workers.Add(new Worker());
            _threads.Add(new Thread(_workers.Last().PumpMessages));
            _threads.Last().Start();
        }
    }
}

public class Worker
{
    private bool _shouldStop = false;

    public void PumpMessages()
    {
        while (!_shouldStop)
        {
            //does cool stuff until told to stop
        }
    }

    public void RequestStop()
    {
        _shouldStop = true;
    }
}
4

2 に答える 2