Workflow, Ablaufsteuerung oder Ähnlich



  • Servus Leute,

    im Prinzip fehlt mir glaube ich der Begriff, nach dem ich eigentlich suchen soll.
    Ich möchte eine Applikation entwickeln, bei der zu bestimmten Zeitpunkten bestimmte Aktionen ausgeführt werden sollen. Dem Benutzer soll es aber möglich sein, dies vorzugeben, z.B. durch eine Eingabe vorzunehmen à la:

    Start
    Zu Zeitpkt A mache F(0.3333) 
    Zu Zeitpkt B mache F(0.6666)
    Zu Zeitpkt C mache F(3.1415)
    Zu Zeitpkt D mache F(11)
    Zu Zeitpkt E mache F(9)
    ...
    Ende
    

    Die Applikation soll diese Anweisungen dann abarbeiten. Wie nennt man so eine Steuerung? Workflow? Und wie realisiert man sowas in .NET? Ist es nicht sehr ineffektiv etwas zu basteln, was alle Millisekunde folgendes macht:

    Ist Zeitpunkt erreicht?
    Ja: mache F(x) und lese nächsten Zeitpunkt
    Nein: mach nix
    

    Danke und Gruß,
    PCMan



  • Das ist aber meines Wissens nach die übliche Herangehensweise. Einen Timer setzen und prüfen ob diese Zeit erreicht ist.

    Alternativ kannst du in Windows einen Scheduled Task einrichten der dann deine Applikation aufruft.

    Je ein Beispiel:
    http://stackoverflow.com/questions/18611226/c-how-to-start-a-thread-at-a-specific-time
    http://stackoverflow.com/questions/3243348/how-to-call-a-method-daily-at-specific-time-in-c



  • PCMan schrieb:

    Wie nennt man so eine Steuerung? Workflow?

    cron, kalender, scheduler?

    PCMan schrieb:

    Und wie realisiert man sowas in .NET? Ist es nicht sehr ineffektiv etwas zu basteln, was alle Millisekunde folgendes macht:

    Ist Zeitpunkt erreicht?
    Ja: mache F(x) und lese nächsten Zeitpunkt
    Nein: mach nix
    

    C# ist ineffektiv, also warum sich Gedanken drüber machen? 😃

    Effizient gehts z.B. so:

    Kalendereinträge von Datei lesen und pro Eintrag ein C#-Objekt anlegen.
    Mit Basisklasse und Vererbung kannste sehr fein auch Sachen wie stündliche/tägliche Wiederholung, Zeitintervalle, Geburtstage, beim Hoch- Runterfahren und jeden Rotz einbauen, ohne daß das Prog echt komplexer wird.

    Jeder Eintrag hat ne

    public override DateTime calcNextShot(DateTime now)
    

    Stopf alle Einträge in eine PriorityQueue, dann kann die Schleife immer genau bis zu dem sleepen, der als nächstes dran ist, und ihn anschließend neubewerten.



  • PCMan schrieb:

    Servus Leute,

    Die Applikation soll diese Anweisungen dann abarbeiten. Wie nennt man so eine Steuerung? Workflow? Und wie realisiert man sowas in .NET? Ist es nicht sehr ineffektiv etwas zu basteln, was alle Millisekunde folgendes macht:

    Je nachdem, um welche Zeiträume und um welche Genauigkeitsanforderungen es sich hier handelt reicht vielleicht schon ein Sleep()?
    Also sobald die Anforderung (Benutzereingabe) für einen neuen Task reinkommt, einfach einen Thread zur Abarbeitung starten, welcher als Parameter die Sleep - Zeit mitbekommt.
    Der Thread startet und wartet dann. Wenn der Sleep Wert groß genug ist (>ein paar Hundert ms), dann wird der Thread tatsächlich schlafen gelegt, sprich: der frisst dann keine CPU Zeit.



  • fdsdfsdf schrieb:

    Wenn der Sleep Wert groß genug ist (>ein paar Hundert ms), dann wird der Thread tatsächlich schlafen gelegt, sprich: der frisst dann keine CPU Zeit.

    Wenn der Wert nicht groß genug ist, dann wird er zumindest unter Windows auf den minimalen Sleep Wert (per default 15ms) gesetzt.



  • Mechanics schrieb:

    fdsdfsdf schrieb:

    Wenn der Sleep Wert groß genug ist (>ein paar Hundert ms), dann wird der Thread tatsächlich schlafen gelegt, sprich: der frisst dann keine CPU Zeit.

    Wenn der Wert nicht groß genug ist, dann wird er zumindest unter Windows auf den minimalen Sleep Wert (per default 15ms) gesetzt.

    habe dunkel in Erinnerung, dass ein Task Wechsel (Thread Wechsel) vom OS Scheduler erst ab einem Mindestwert einsetzt, darunter ist Sleep als "busy wait" implementiert, d.h. der Thread verbratet Zeit indem er sich in einer Schleife dreht.
    Weiß aber nicht mehr ob das bei Windows war!?



  • Hallo,
    danke für die Tipps und Entschuldigung für meine späte Antwort, das war unfreundlich 😉
    Also mir geht es nicht darum, dass die Events regelmäßig gefeuert werden. Für sowas gibt es ja bereits Timer, Cronjobs, Taskplaner etc. Ich stelle mir das eher so vor, wie dass Eingaben eines Benutzers abgearbeitet werden, also eine Art generische Programmsteuerung. Die Basiseinheit dazu muss auch nicht unbedingt Zeit sein. Ich gebe mal weitere Beispiele an:

    Z.B. Waschmaschine:
    Start: drehe im Uhrzeigersinn mit 20 u/min
    Nach 200 Umdrehungen: drehe gegen Uhrzeigersinn mit 1500 u/min
    Nach 6000 Umdrehungen: drehe im Urzeigersinn mit 50 u/min
    Nach 400 Umdrehungen: Programmende
    ...
    
    Z.B. Roboterfahrwerk:
    Start: Motor rechts 200 Schritte mit 10 1.4km/h
    Nach 200 Schritte: Motor links und rechts 1000 Schritte mit 4km/h
    Nach 1000 Schritte: Motor links 200 Schritte mit 0.2km/h
    ...
    

    Es wird also nur ein Sollzustand eingegeben. Dabei soll sich z.B. der Motor nicht drum kümmern müssen, dass er nur 1000 Schritte machen soll. Er soll einfach mit einer gewissen Geschwindigkeit drehen. Irgendein Beobachter bemerkt dann, dass die Sollschrittzahl erreicht wurde und leitet dadurch den nächsten Befehl ein (z.B. Jetz Motor links mit Geschwindigkeit y drehen).

    Ich kann mir schon vorstellen, dass man das mit mehreren Threads lösen kann. Doch bevor man das Rad nochmals erfindet, dachte ich, ich frage mal die Kenner, ob es sowas in der Gestalt schon gibt? Und mir kam es eben irgendwie ineffektiv vor, etwar zu bauen, dass alle µS aufgerufen wird, um zu prüfen, ob ein Sollzustand X eingetroffen ist um dann den nächsten Befehl aufzurufen.

    Danke vielmals!



  • Das hat jetzt nichts mit Threads zu tun (nur ein technisches Detail, interessiert nicht) und die Anforderung ist immer noch reichlich abstrakt. Es gibt schon alles mögliche. Die Frage ist, was du ganz genau brauchst, und ob es irgendwas, was es schon gibt, auch dazu passt. So wie du das beschrieben hast, würde ich das vermutlich selber programmieren.
    Ein Stichwort in dem Zusammenhang könnte evtl. Complex Event Processing sein. Oder vielleicht auch Business Rules Engine. Aber da kommst du vom hundertsten ins tausendste.



  • PCMan schrieb:

    Die Basiseinheit dazu muss auch nicht unbedingt Zeit sein.

    Ist sie aber doch in allen Deinen Beispielen. Ob das jetzt Sekunden, Schritte oder Umdrehungen sind ist doch egal. Selbst die dümmlichen Thread/Sleep-Lösungen sollten aus Erfahrung eine/mehrere innere Uhr(en) mitführen und nur diese in den loops anhand der äußeren Uhr aktualisieren.
    Was hat Dir an meiner Lösung nicht gepaßt, außer daß sie auch mit 1000000000 Jobs noch lange nicht abkackt und viel zu einach zu pr0ggern und zu erweitern ist?

    Oder haste mehr Sensoren? Neben dem globalen Timer auch den Laugenpumpenschalter, den Türkontakt, den Mütorüberhitzungsschalter und den Intragehäuseüberschwemmungsschutzsensor? Falls ja, sag das. Und dann sag an, welche Größenordnung Du anstrebst. Anscheinend nicht 1000000000 Jobs, sondern nur 3 Jobs und niemals mehr als 5. Falls mehr als 10, muss der Kunde eben ein Produktupdate pr0ggern lassen oder fette Hardware hinstellen.



  • Hallo,

    Mechanics:
    Ich habe mal während des Studiums sowas wie einen Pipettierroboter gebaut. Die Dinger gibt es natürlich schon kommerziell mit weitaus besserer Konstruktion und Intelligenz. Ich dachte daran, das Teil mal wieder in Angriff zu nehmen. Aus Spaß am Basteln. Und dazu ist eine "Ablaufsteuerung" nötig. Ich dachte eben, man könnte das etwas generischer realisieren, so dass man es später für andere Zwecke hernehmen kann und was nicht auf bestimmte Einheiten fixiert ist.

    volkhard:
    So wie ich es verstanden hatte, schlägst du Möglichkeiten vor, Events in festgelegten Intervallen zu feuern. Bestimmt kann man die Steuerung auch nach deinem Vorschlag so umsetzen. Ich wollte ja nur mal fragen, ob es andere/klügere/generische/cewwlazz Ansätze gibt.

    Frage ich mal andersherum: Wenn ein erfahrener Enwtickler die Sache angehen würde, schreibt der dann ganz spezifische Lösungen nur für diesen einen Fall? Oder entwickelt er etwas generisches, z.B. eine Steuerung, die sowohl den Aquariumfutterautomaten als auch den Rasensprenger bedienen kann?

    Grüße



  • Hallo, ich würde soetwas (wenn in einem C# Programm) wie folgt machen:

    /// <summary>
        /// base class for tasks
        /// </summary>
        public abstract class Task
        {
            /// <summary>
            /// gets or sets the execution interval
            /// </summary>
            public TimeSpan Interval { get; set; }
    
            /// <summary>
            /// gets or sets the time of the last execution
            /// </summary>
            public DateTime LastExecution { get; set; }
    
            /// <summary>
            /// Method to execute the task
            /// </summary>
            /// <returns>true if the task executed successfull</returns>
            public abstract bool Execute();
        }
    
    /// <summary>
        /// class for scheduling tasks
        /// </summary>
        public class TaskScheduler
        {
            #region Fields
    
            private bool _bStarted = false;
            private Thread _scheduleThread;
            private Object _scheduleLock = new Object();
            private Object _queueLock = new object();
            private Queue<Task> _tasksToAdd = new Queue<Task>();
    
            private List<Task> _tasks = new List<Task>();
    
            private int _executionInterval = 1000;
    
            #endregion
    
            #region Methods
    
            /// <summary>
            ///  Method to start the scheduler
            /// </summary>
            public void Start(int executionInterval)
            {
                this._executionInterval = executionInterval;
                if (this._bStarted)
                    return;
    
                this._scheduleThread = new Thread(new ThreadStart(ScheduleWorker));
                this._scheduleThread.IsBackground = true;
                this._scheduleThread.Name = "ScheduleThread";
                this._scheduleThread.Start();
            }
    
            /// <summary>
            /// Method to stop the scheduler
            /// </summary>
            public void Stop()
            {
                this._scheduleThread = null;
    
                this.ForceSchedule();
            }
    
            /// <summary>
            /// Method to append a task
            /// </summary>
            /// <param name="task">the task to append</param>
            public void AppendTask(Task task)
            {
                lock (this._queueLock)
                {
                    this._tasksToAdd.Enqueue(task);
    
                    this.ForceSchedule();
                }
            }
    
            /// <summary>
            /// Method to force the scheduling worker
            /// </summary>
            private void ForceSchedule()
            {
                lock (this._scheduleLock)
                {
                    Monitor.Pulse(this._scheduleLock);
                }
            }
    
            private void ScheduleWorker()
            {
                do
                {
                    lock (_queueLock)
                    {
                        // add tasks
                        while (this._tasksToAdd.Count > 0)
                        {
                            Task task = this._tasksToAdd.Dequeue();
                            this._tasks.Add(task);
                        }
                    }
    
                    // check exectution of each task
                    foreach (Task task in this._tasks)
                    {
                        if (task.LastExecution < DateTime.Now.Subtract(task.Interval))
                        {
                            if(task.Execute())
                               task.LastExecution = DateTime.Now;
                        }
                    }
    
                    lock (this._scheduleLock)
                    {
                        Monitor.Wait(this._scheduleLock, this._executionInterval);
                    }
                }
                while (Thread.CurrentThread == _scheduleThread);
    
                this._bStarted = false;
            }
    
            #endregion
        }
    

    Achtung: Der Code dient nur zur Veranschaulichung, ist sicher weder zu 100% korrekt noch vollständig.



  • PCMan schrieb:

    Frage ich mal andersherum: Wenn ein erfahrener Enwtickler die Sache angehen würde, schreibt der dann ganz spezifische Lösungen nur für diesen einen Fall? Oder entwickelt er etwas generisches, z.B. eine Steuerung, die sowohl den Aquariumfutterautomaten als auch den Rasensprenger bedienen kann?

    In C++ würde man wahrscheinlich etwas mehr oder weniger minimalistisches selber schreiben. In Java würde man ein fettes fertiges Framework nehmen, das um viele Größenordnungen komplexer als das eigentliche Problem ist. In C# vielleicht etwas dazwischen.

    Ich seh bei der Beschreibung erstmal noch nichts, was nach irgendwas fertigem schreit. Irgendsowas wie den Vorschlag von volkard oder inflames2k kann jeder schnell umsetzen und dann erweitern/anpassen, wie man es braucht, oder wie es einem gefällt.

    Ich mache ehrlich gesagt öfter mal Lösungen, die mir Spass machen, und nicht die, die meiner Meinung nach optimal oder ausreichend wären. Wenn mich weder das Problem noch die Lösung interessiert, dann mache ich irgendwas minimalistisches und gut ist. Wenn mich das Problem nicht interessiert, aber ich mir eine Lösung als abstraktes, wiederverwendbares Framework vorstellen kann, dann mache ich das vielleicht. Und vielleicht verwende ich das dann auch tatsächlich an ganz anderen Stellen wieder. Das ist durchaus schon paar mal vorgekommen. Aber dabei kenne ich die Anforderungen schon. Wir schreiben ein sehr umfangreiches Programm in der Arbeit und wenn ich sowas framework-ähnliches bastle, dann habe ich schon im Hinterkopf, wo ich das noch verwenden könnte und was ich dafür wahrscheinlich brauchen werde.



  • PCMan schrieb:

    Frage ich mal andersherum: Wenn ein erfahrener Enwtickler die Sache angehen würde, schreibt der dann ganz spezifische Lösungen nur für diesen einen Fall? Oder entwickelt er etwas generisches, z.B. eine Steuerung, die sowohl den Aquariumfutterautomaten als auch den Rasensprenger bedienen kann?

    Das hängt massiv vom Unternehmen ab, wo man arbeitet. Optimalerweise arbeitest Du in einem an eine Hochschule angeschlossenen Forschungsinstitut und hast da einen Namen. Und dann machste weder das eine noch das andere.

    Im "real life" haste derzeit Chefs über Dir, die zur Zeit entweder SCRUM ums Verrecken oder 80er-Jahre-Stil durchboxen.

    Du bist der einzige Programmieraffe, der gelegentlich ein Buch liest; und wirst bald den Ruf haben, zaubern zu können.


Anmelden zum Antworten