2011-10-20 3 views
5

私が開発しているアプリケーションでは、単純にそこに座ってログデータを表示するメインフォームと、自律的にループを実行するワーカースレッドがあります。スレッドを正常にシャットダウンする

ご覧のとおり、フォームが閉じられるたびに、ワーカースレッドを停止する必要があります。労働者は、次のようになります。あなたが見ることができるように

public class MyWorker 
{ 
    public String Running { get; set; } 

    public MyWorker() 
    { 
     Running = true; 
    } 

    public void MainLoop() 
    { 

     while (Running) 
     { 

      DoExtensiveWork1(); 
      if (!Running) return; 

      DoExtensiveWork2(); 
      if (!Running) return; 

      DoExtensiveWork3(); 
      if (!Running) return; 

      DoExtensiveWork4(); 
      if (!Running) return; 

      DoExtensiveWork5();   
      if (!Running) return; 

      // We have to wait fifteen minutes (900 seconds) 
      // before another "run" can be processed 
      for (int i = 0; i < 900; i++) 
      { 
       Thread.Sleep(1000); 
       if (!Running) return; 
      } 
     } 
    } 
} 

が、私はスレッドが連続した作業の操作を切り替える際に停止することができるようにしたいが、ない場合の動作範囲内。操作(DoExtensiveWorkN)が終了すると、その状態と結果はディスクまたはデータベースで保持されるため、操作の進行中に終了する(たとえば、Thread.Abortなど)はオプションではありません。

Runningに設定されていることを検出する前にスレッドがアイドル状態にならないように、特に私はこのコードを見て、特に1秒間スリープする "待機ループ" false

私はむしろ、仕事を終えるとすぐにメインループを停止するために何らかのイベントをスローすることができます。

これを行う方法を正しい方法で教えてもらえますか、スレッドが誤解されているために全面的な書き換えが必要な場合は、その原則が説明されている場所を教えてください。

答えて

13

個々のタスクの実行と15分の待機ループの両方をきちんと整理できます。

私は、おそらくこのような何かを使用することをお勧めしたい:

public class MyWorker 
{ 
    private readonly ManualResetEvent _stopEvent = new ManualResetEvent(false); 
    private readonly Action[] _workUnits; 

    private bool Running 
    { 
     get { return !_stopEvent.WaitOne(0); } 
    } 

    public MyWorker() 
    { 
     _workUnits = new Action[] 
     { 
      DoExtensiveWork1, 
      DoExtensiveWork2, 
      DoExtensiveWork3, 
      DoExtensiveWork4, 
      DoExtensiveWork5 
     }; 
    } 

    public void Stop() 
    { 
     _stopEvent.Set(); 
    } 

    public void MainLoop() 
    { 

     while (Running) 
     { 
      foreach (var workUnit in _workUnits) 
      { 
       workUnit(); 
       if (!Running) return; 
      }   

      // We have to wait fifteen minutes (900 seconds) 
      // before another "run" can be processed 
      if (_stopEvent.WaitOne(900000)) return; 
     } 
    } 
} 

は、その後、次の適切なポイントでプロセスを停止する:

Worker.Stop(); 
0

私はSystem.Timers.Timerを使用してお勧めします。

実行中のもので作業を行うことができます。スリープを使用するのではなく、15分後にもう一度タイマーを設定することができます。

これを早期に停止したい場合は、タイマーを停止する何らかのアボートメソッド(Running = true変数の設定と同様)を呼び出します。

タイマーイベントが発生するたびに新しいスレッドが起動するので、バックグラウンドスレッドを削除する心配はありません。あなたのスレッドは処理の実行を終了し、15分後にタイマーを実行し、その後スレッドは自然に終了します。あなたが待っている間に中断した場合、あなたはタイマーを取り除き、必要なクリーンアップはもう必要ありません。実行中に中断した場合は、実行を終了させ、最後にフラグをチェックし、タイマーを再び開始せずにスレッドが終了します。

タイマーの場合、プロセスの最後にタイマーを手動で開始するように設定する必要があります。別の方法として、15分ごとにタイマーを立てることがありますが、それは処理に10分かかり、次の実行までに5分しかかからないことを意味します。そして15分以上かかると困っているかもしれません。また、タイマーを手動で再起動すると、別のタイマーが実行されている間に処理が再開されないようになります。

+0

タイマーは主な問題を解決しません。フォームが閉じられても作業を続行したくないので、チェックを続けるためにたくさんのコードを追加したくありません。 – CodeCaster

+0

@コードキャスター:ああ、私は誤解していました。「スレッドが実行されている間に終了する(例えば、Thread.Abortなど)はオプションではありません」と誤解されていました。私の思想は一連のアクションを使用していましたが、イリジウムは私にそれを打ち負かしました。私はまだ15分待ってもタイマーを好む。 :) – Chris

+0

私はそれをもっとはっきりと説明できました。しかし、提案をありがとう。 :-) – CodeCaster

関連する問題