2016-05-24 9 views
4

Ich habe über 20 Funktionen erhalten, sollten einige von ihnen einmal pro Sekunde abgefeuert werden, einige, 20-mal pro Sekunde und zweimal eine Minute Zeit habe ich so etwas wie dieses:C# Richtiger Weg periodisch Brennen Funktionen

   DateTime nowVar = DateTime.Now; 
       var lastExecutionFunc1 = nowVar; 
       var lastExecutionFunc2 = nowVar; 
       var lastExecutionFunc3 = nowVar; 
       var lastExecutionFunc4 = nowVar; 

     DateTime _now = DateTime.Now; 


       if ((_now - lastExecutionFunc1).TotalSeconds >= 0.1) 
         { 
          lastExecutionFunc1 = _now; 
          //dosomething 
         } 
       if ((_now - lastExecutionFunc2).TotalSeconds >= 0.5) 
         { 
          lastExecutionFunc2 = _now; 
          //do something else 
         } 
       if ((_now - lastExecutionFunc3).TotalSeconds >= 30) 
         { 
          lastExecutionFunc3 = _now; 
          //do something else 
         } 
..... 

Während dies funktioniert, kann ich nicht umhin zu denken, dass es eine elegantere Art und Weise, dies zu tun sein sollte. Das Erstellen einer var zum Speichern jeder Ausführung lässt den Kern sehr unordentlich erscheinen. Ich denke, ich könnte paar, aber das wäre auch nicht zu schön.

Jede Beratung?

EDIT: Wenn Sie möchten, um zu sehen, was ich versuche, you can see the whole code here zu erreichen. In Zeile 525.

+6

Sie Timer-Klasse verwenden können, https://msdn.microsoft.com/en-us/library/system.windows.forms.timer(v=vs.110).aspx – Adil

+0

Was ist ein Array erstellen von Funktionen, die Sie dann aufgrund eines steigenden Zählers direkt in Ihren Timer-Callback einspeisen können? – Robert

+0

Die einfachste Lösung ist die Verwendung von [Timer-Klasse] (https://msdn.microsoft.com/en-us/library/system.timers.timer%28v=vs.110%29.aspx) – shadow

Antwort

3

Im Folgenden Code stellt einen grundlegenden Planer mit Synchronisationssperre.

using System; 
using System.Collections.Generic; 
using System.Timers; 

namespace TimerUsage 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      Scheduler scheduler = new Scheduler(); 
      scheduler.ScheduleMethod(100,() => Console.WriteLine("func1")); 
      scheduler.ScheduleMethod(200,() => Console.WriteLine("func2")); 
      scheduler.ScheduleMethod(300,() => Console.WriteLine("func3")); 
      scheduler.ScheduleMethod(1000,() => Console.WriteLine("func4")); 
      scheduler.Run(); 
      System.Threading.Thread.Sleep(10000); 
     } 

    } 

    public class Scheduler 
    { 
     private Dictionary<int, Row> _schedule = new Dictionary<int, Row>(); 

     public void ScheduleMethod(int interval, Action method) 
     { 
      Row row; 
      if (!_schedule.TryGetValue(interval, out row)) 
      { 
       row = new Row(interval); 
       _schedule[interval] = row; 
      } 
      row.AddMethod(method); 
     } 

     public void Run() 
     { 
      foreach (var item in _schedule) 
      { 
       item.Value.StartTimer(); 
      } 
     } 
    } 

    internal class Row 
    { 
     private object _syncLock = new object(); 
     private Timer _timer; 
     private List<Action> _methods = new List<Action>(); 

     public Row(int interval) 
     { 
      _timer = new System.Timers.Timer(interval); 
      _timer.Elapsed += ExecuteItems; 
     } 

     private void ExecuteItems(object sender, ElapsedEventArgs e) 
     { 
      lock (_syncLock) 
      { 
       foreach (var method in _methods) 
       { 
        method(); 
       } 
      } 
     } 

     public void AddMethod(Action method) 
     { 
      _methods.Add(method); 
     } 

     public void StartTimer() 
     { 
      _timer.Start(); 
     } 

    } 

} 
+0

Benim kulanim alanım için biraz fazla teferruatlı duruyor ama teşekkürler. – flanker

+0

Rica Ederim. Classy's kopyalayarak kilay bir şekilde kullanabilirsiniz, teferruat kısmı kullanım zorluğu oluşturmayacaktır. –

3

Haben Sie eine infinty Schleife für diese Ereignisse zeitlich geschrieben hat? Sehr schlechte Übung. Wenn einer von Ihnen "etwas tun" lange dauert, funktionieren alle anderen Funktionen (und das Hauptprogramm) nicht mehr. Wenn Ihre Funktionen unabhängig arbeiten können, lassen Sie sie unabhängig voneinander arbeiten und verwenden Sie für jeden einen anderen Timer. Wenn einige Funktionen exklusiv sind, verwenden Sie Semaphoren (statische Elemente), um ein paralleles Arbeiten zu vermeiden. Hier

+0

Ich glaube nicht, dass das hier das Problem ist. Wenn 20 Timer in einem einzigen Formular gespeichert sind, scheint das eine Verschwendung von Ressourcen zu sein, wenn ein einzelner Timer alle 20 Methoden verarbeiten kann. Natürlich sollten sie möglichst "async" sein. –

+0

Ja, sie sind in while (true) Block, aber sie arbeiten an einem anderen Thread als das Hauptprogramm auch gibt es keine Chance für jede Funktion mehr als ein paar Taktzyklen zu nehmen. Sie nehmen einfach eine Zeichenfolge von irgendwo und kopieren sie in eine andere Zeichenfolge. – flanker

1

ist eine Möglichkeit, es zu tun:

ich eine Klasse erstellt haben, die die Methode binden damit Intervall ist, mit dem Action Delegierten:

public class ActionInvoker 
{ 
    private DateTime _LastRunTime; 
    private Action _Action; 
    private double _Interval; 

    public ActionInvoker(Action action, double interval) 
    { 
     _Action = action; 
     _Interval = interval; 
     _LastRunTime = DateTime.Now; 
    } 


    public void InvokeAction() 
    { 
     var now = DateTime.Now; 
     if ((now - _LastRunTime).TotalMilliseconds >= _Interval) 
     { 
      _LastRunTime = now; 
      _Action.Invoke(); 
     } 
    } 

Ich habe eine Liste von ActionInvoker hinzugefügt als privates Mitglied der Form:

private List<ActionInvoker> _Actions; 

nun in der Konstruktor der Form habe ich das getan:

_Actions = new List<ActionInvoker>(); 

_Actions.Add(new ActionInvoker(DoThis, 10000)); 
_Actions.Add(new ActionInvoker(DoThat, 3000)); 

Jetzt alles, was ich in der Timer.Tick Ereignishandler haben, ist dieser Code:

foreach(var ai in _Actions) 
{ 
    ai.InvokeAction(); 
} 

Natürlich ist dies nur eine grundlegende POC, müssen Sie es weiter entwickeln, wenn Sie senden möchten Parameter zu den Methoden oder wenn Ihre Methoden Werte zurückgeben.

Beachten Sie auch, Sie besser diese Methoden als async laufen die Benutzeroberfläche zu verhindern, dass das Einfrieren, bis sie fertig sind.

+0

Dies scheint ein guter Weg, um es zu tun. Aber ich bin mir nicht sicher, ob ich verstehe, wie das "Action" -Geschäft funktioniert.Was soll ich darauf übertragen? Übrigens, die Funktionen, die ich ausführe, nehmen keine Parameter und geben auch nichts zurück. Sie modifizieren nur einige Globals. Ich habe einen Link zu meinem Projekt im ursprünglichen Post hinzugefügt, wenn Sie den Code sehen möchten. – flanker

+0

Ich habe meine Antwort so bearbeitet, dass sie den Link zur MSDN-Seite für den Delegierten "Aktion" enthält. –

+0

Ja, ich habe etwas über den Aktionstyp gelesen. Scheint sehr nützlich, wundern Sie sich, wie ich es bis jetzt nie bemerkt habe. Vielen Dank. – flanker

Verwandte Themen