3

基本的に次のコードを実行する Windows サービスに取り組んでいます。

public class ServiceController
{
  private FundsEngine _fundsEngine;

  protected override void OnStart(string[] args)
  {
    var logsPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "logs");
    if (Directory.Exists(logsPath) == false)
    {
      Directory.CreateDirectory(logsPath);
    }

    _fundsEngine = new FundsEngine();
    _fundsEngine.Start();
  }
}

このサービスは、タイマーを使用して指定された間隔でコードを実行するクラスである「エンジン」を起動できます。

次のクラスは、 を使用して 5 秒ごとにSystem.Threading.Timerコールバックを呼び出すエンジンの例です。OnTick()

public class FundsEngine
{
  private System.Threading.Timer _timer;
  private static Logger _logger = LogManager.GetCurrentClassLogger();

  public void Start()
  {
    _logger.Trace("Begin Start");

    try
    {
      // details omitted

      _timer = new Timer(OnTick);
      _timer.Change(5000, Timeout.Infinite);
    }
    catch (Exception exception)
    {
      _logger.ErrorException("Error in Start.", exception);
    }
    finally
    {
      _logger.Trace("End Start");
    }
  }

  private void OnTick(object state)
  {
    _logger.Trace("Begin Tick");

    try
    {
      // do stuff
      _timer.Change(5000, Timeout.Infinite);
    }
    catch (Exception exception)
    {
      _logger.ErrorException("Error in Tick. ", exception);
    }
    finally
    {
      _logger.Trace("End Tick");
    }
  }
}

以下のログに示すように、Timer は期待どおりに機能し、OnTick()5 秒ごとにメソッドを呼び出します。

2013-05-14 16:27:01.2261|TRACE|Begin Start 
2013-05-14 16:27:03.8514|TRACE|End Start 
2013-05-14 16:27:08.8569|TRACE|Begin Tick 
2013-05-14 16:27:08.8709|TRACE|End Tick 
2013-05-14 16:27:13.8734|TRACE|Begin Tick 
2013-05-14 16:27:13.8734|TRACE|End Tick 
2013-05-14 16:27:18.8809|TRACE|Begin Tick 
2013-05-14 16:27:18.8809|TRACE|End Tick 
2013-05-14 16:27:23.8894|TRACE|Begin Tick 
2013-05-14 16:27:23.8894|TRACE|End Tick 
2013-05-14 16:27:28.8969|TRACE|Begin Tick 
2013-05-14 16:27:28.8969|TRACE|End Tick 
2013-05-14 16:27:33.9044|TRACE|Begin Tick 
2013-05-14 16:27:33.9044|TRACE|End Tick 

メソッドで例外がキャッチされたOnTick()場合、それがログに記録され、サービスが実行を継続し、OnTick()メソッドが 5 秒後に再度呼び出されることを期待しています。ただし、例外が処理された後にコールバックが再度呼び出されることはないため、これは当てはまりません。どうしてこれなの?

2013-05-14 16:29:03.8574|TRACE|Begin Start 
2013-05-14 16:29:03.8574|TRACE|End Start 
2013-05-14 16:29:08.8709|TRACE|Begin Tick 
2013-05-14 16:29:09.9750|ERROR|Error in Tick.  System.Net.Sockets.SocketException (0x80004005): No connection could be made because the target machine actively refused it 127.0.0.1:22
2013-05-14 16:29:09.9750|TRACE|End Tick
4

2 に答える 2

2
  _timer.Change(5000, Timeout.Infinite);

期間タイマーを作成せず、期間引数に Infinite を渡しました。タイマーは OnTick() を 1 回だけ呼び出します。ただし、コードは非常に不完全です。それが機能する唯一の方法は、Change() を再度呼び出してタイマーを再充電することです。

この Change() 呼び出しが例外によってバイパスされる可能性が非常に高いです。それを続けたい場合は、この Change() 呼び出しはfinallyブロックに属します。これを行うのは実際には良い考えではありませんが、プロセスの状態が破損し、再びクラッシュする可能性がゼロではない可能性があります。何度も。せめてこれだけの対策をして、連打回数も数えて、ただ連打するだけなら諦めてください。

于 2013-05-15T16:18:44.067 に答える
1

このStackOverflow投稿で受け入れられた回答は、例外が発生した場合に...

System.Threading.Timerプログラムを終了します。

あなたが見ているものだと私は信じています。

于 2013-05-15T13:41:36.387 に答える