2016-07-29 6 views
0

自動化されたタスクを実行するために使用したサービスに問題があります。 サービスはタイマを使用し、20秒後に実行されます。実行時に重複するタイミングイベント

実行される機能は、データベースを開き、そこから読み取り、ネットワークを介して値を送信し、応答を受け取り、その応答でデータベースを更新します。

データベースで約1000行の自動化されたタスクを実行し、システムが失敗してしまうまでうまくいきました。私のログを調べた後、私は、前のインスタンスがまだ実行中であっても、その間隔の後に関数が実行されることを発見しました。この関数はメッセージを送信することになっており、一部のクライアントはメッセージを受け取らなかったと訴えているが、他のクライアントは6時間も受け取っている。

以前のインスタンスがまだ実行中の場合に関数が実行されないことを確認する簡単で効率的な方法はありますか?

私が起動し、機能の時間を停止した場合、それだけで追加されます。ここ間隔

までの時間を「合格」はあなたがマルチを使用しているコード

public partial class Service1 : ServiceBase 
{ 
    private Timer timer1 = null; 

    public Service1() 
    { 
     InitializeComponent(); 
    } 

    protected override void OnStart(string[] args) 
    { 
     timer1 = new Timer(); 
     this.timer1.Interval = 20000; 
     this.timer1.Elapsed += new System.Timers.ElapsedEventHandler(this.timer1_Tick); 
     timer1.Enabled = true; 
     Library.WriteErrorLog("service has started"); 
    } 

    private void timer1_Tick(object sender, ElapsedEventArgs e) 
    { 
     try 
     { 
     //retrieve data from database 
     //read rows 

     //Loop through rows 
     //send values through network 
     //receive response and update db 
     } 
     catch (Exception ex) 
     { 
      Library.WriteErrorLog(ex); 
     } 
    } 
} 

    protected override void OnStop() 
    { 
     timer1.Enabled = false; 
     Library.WriteErrorLog("service has stopped"); 
    } 
} 
+0

他のことをする前にタイマーを止めて、それを '' 'finally''で再起動すれば十分でしょうか?または、何を問わずタイマーを稼働させたいと思いますか?これにより、常に1つのタイマーしか実行されなくなります。 –

+0

@Kevin Leeのお返事ありがとうございます。 – elfico

答えて

1

です-threaded System.Timers.Timer各ElapsedイベントのThreadPoolから新しいスレッドのtimer1_Tickコールバックを呼び出します。変数を使用して実行を同期させます。

public partial class Service1 : ServiceBase 
    { 

     private Timer timer1 = null; 
     private long isTaskRunning = 0; 

     public Service1() 
     { 
      InitializeComponent(); 
     } 

     protected override void OnStart(string[] args) 
     { 
      timer1 = new Timer(); 
      this.timer1.Interval = 20000; 
      this.timer1.Elapsed += new System.Timers.ElapsedEventHandler(this.timer1_Tick); 
      timer1.Enabled = true; 
      Library.WriteErrorLog("service has started"); 
     } 

     private void timer1_Tick(object sender, ElapsedEventArgs e) 
     { 
      try 
      { 

      if (Interlocked.CompareExchange(ref isTaskRunning, 1, 0)==1) 
      { 
      return; 
      } 

      //retrieve data from database 
      //read rows 

      //Loop through rows 
      //send values through network 
      //receive response and update db 
      } 
      catch (Exception ex) 
      { 
       Library.WriteErrorLog(ex); 
      } 
      finally 
      { 
      Interlocked.Exchange(ref isTaskRunning, 0); 
      } 
     } 
    } 

     protected override void OnStop() 
     { 
      timer1.Enabled = false; 
      Library.WriteErrorLog("service has stopped"); 
     } 
    } 
+0

コードに 'System.Timers'を使用しましたが、' InterLock'は 'System.Threading.Timer'のメソッドです。これは矛盾を起こさないでしょうか?私の多くの疑問を残して申し訳ありません、私はスレッディングに少し慣れています。ありがとう – elfico

+0

矛盾はありません。コールバックは、同時に複数のスレッドによって実行されることはありません。これはインターロックされたメソッドによって防止されます – radianz

+0

応答をありがとう。 – elfico

1
private void timer1_Tick(object sender, ElapsedEventArgs e) 
{ 
    Timer timer = sender as Timer; 
    timer.Enabled = false; // stop timer 
    try 
    { 
     //retrieve data from database 
     //read rows 

     //Loop through rows 
     //send values through network 
     //receive response and update db 
    } 
    catch (Exception ex) 
    { 
     Library.WriteErrorLog(ex); 
    } 
    finally 
    { 
     timer.Enabled = true; // start timer again, no overlapping 
    } 
} 
関連する問題