2016-07-29 22 views
0

Ich habe ein Problem mit dem Dienst, den ich für die Ausführung automatisierter Aufgaben verwendete. Der Dienst verwendet einen Timer und wird nach 20 Sekunden ausgeführt.Zeitgesteuerte Ereignisse, die sich während der Ausführung überschneiden

Die Funktion, die ausgeführt wird, öffnet die Datenbank, liest daraus, sendet die Werte über das Netzwerk, empfängt eine Antwort und aktualisiert die Datenbank mit dieser Antwort.

Es funktioniert gut, bis ich die automatisierten Aufgaben für etwa 1000 Zeilen in der Datenbank ausführen wollte und das System 'fehlgeschlagen'. Nachdem ich meine Protokolle überprüft hatte, fand ich heraus, dass die Funktion nach dem Intervall ausgeführt wird, auch wenn eine vorherige Instanz noch ausgeführt wird. Die Funktion soll eine Nachricht senden und einige Kunden haben sich darüber beschwert, dass sie keine Nachricht erhalten, während andere bis zu sechs Mal Zeit haben.

Gibt es eine einfache und effiziente Möglichkeit, um sicherzustellen, dass die Funktion nicht ausgeführt wird, wenn eine vorherige Instanz noch ausgeführt wird.

Wenn ich starte und die Zeit, in der Funktion stoppen, wird es nur hinzufügen, die Zeit, um das Intervall „bestanden“

Hier ist der Code

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

Möchten Sie den Timer in Ihrem Häkchen stoppen, bevor Sie andere Dinge tun und dann wieder in einem '' 'endlich' '' suffice? Oder möchtest du den Timer laufen lassen, egal was? Dies würde sicherstellen, dass immer nur ein Timer zu einem bestimmten Zeitpunkt ausgeführt wird. –

+0

Danke für die Antwort @Kevin Lee. – elfico

Antwort

1

Sie verwenden den Multi -threaded System.Timers.Timer, das den timer1_Tick-Callback für einen neuen Thread vom ThreadPool bei jedem Elapsed-Ereignis aufruft. Verwenden Sie eine Variable, um die Ausführung zu synchronisieren.

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

Ich habe 'System.Timers' für den Code verwendet, aber' InterLock' ist eine Methode in 'System.Threading.Timer'. Wird das keinen Konflikt verursachen? Sorry für meine vielen Fragen, ich bin etwas neu in Threading. Danke – elfico

+0

Es wird keinen Konflikt geben. Der Callback wird nicht gleichzeitig von mehreren Threads ausgeführt. Dies wird durch die Interlocked-Methoden verhindert – radianz

+0

Danke für die Antwort. – 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 
    } 
} 
Verwandte Themen