2010-12-23 28 views
2

Angenommen, ich habe eine Datenbank mit einer Tabelle, jeder Datensatz in dieser Tabelle entspricht einer auszuführenden Aktion. Diese Tabelle hat ein Datetime-Feld, in dem der nächste Moment gespeichert wird, in dem die Aktion ausgeführt werden soll.Laufender zeitgesteuerter Job

Diese Tabelle wird von einem Windows-Dienst gelesen und die Aktionen werden in einer Datenstruktur gespeichert. Alle paar Minuten liest der Dienst die Tabelle und neue Aktionen werden in der Datenstruktur zusammengeführt, so dass in der Zwischenzeit erstellte Aktionen nicht ausgelassen werden.

Jede Aktion hat ein bestimmtes Wiederholungsintervall. Wenn eine Aktion ausgeführt wurde, wird das Datum/Uhrzeit-Feld auf den nächsten Moment aktualisiert, in dem es basierend auf diesem Intervall ausgeführt werden sollte.

Jetzt hier ist, wo ich über die richtige Vorgehensweise frage: Was ist der bevorzugte Weg, um die Aktion bei seiner vorgegebenen Zeit tatsächlich zu starten?

Angenommen, ich habe eine Aktion, die um 09:00 Uhr in der Datenstruktur ausgeführt werden sollte. Wie stelle ich sicher, dass sie um 09:00 Uhr ausgelöst wird? Was ich derzeit im Sinn habe, ist die Datenstruktur jede Minute zu überprüfen, die aktuelle Zeit mit der geplanten Aktion zu vergleichen und, falls sie übereinstimmen, die Aktion auszuführen und die Ausführungszeit der Aktion entsprechend dem zugehörigen Intervall zu aktualisieren.

Als Datenstruktur tendiere ich dazu, in der Warteschlange zu denken, damit ich den nächsten Job vor mir haben kann und nur den ersten prüfen muss, aber dann muss ich die Warteschlange neu anordnen, wenn neue Aktionen gefunden werden.

Mein wichtigster Punkt ist ein guter Ansatz, um zu überprüfen, ob eine Aktion ausgeführt werden sollte, eine geeignete Datenstruktur wird folgen. Die Anzahl der Aktionen in der Tabelle wird sehr niedrig sein, nicht mehr als 25. Ich habe keine Kontrolle über die Datenbank, also sollte alles programmgesteuert in C# erledigt werden, falls Sie sich fragen. Irgendwelche Tipps, Erfahrungen oder Ratschläge?

+0

Haben Sie -need - eine Datenbank? Wer initiiert die geplanten Aufgaben? –

+0

Hängt vom System ab; In einer db (oder ähnlich) können Sie den Systemzustand beibehalten, falls das System umfällt. –

+0

Ja, eine Datenbank wird als zentraler Punkt zum Hinzufügen neuer Aktionen usw. benötigt. Natürlich ist das nur ein kleiner Teil des Systems. Die einzige Diskussion sollte die Art sein, wie die Zeiten überprüft werden. – Oxymoron

Antwort

1

Angenommen, die Granularität beträgt 1 Minute. Ich würde einen Thread die DB häufig abfragen lassen und eine Liste von Sachen aktualisieren, um in der nächsten Minute anzufangen. Ein separater Timer-Thread könnte dann diese Liste von Aktionen starten, sobald die Minute abgelaufen ist.

Wenn Sie in die Details gehen, wird es ein wenig komplizierter, da Sie vielleicht auch die damit verbundenen Zustandsautomaten (vorbereitet, laufen, komplett usw.) in Zaum halten wollen.

+0

Das war, was ich im Sinn hatte und fragte mich, ob dies der bevorzugte Weg ist. – Oxymoron

+0

Nun, es ist ein Weg, und wenn Ihr Service-Level ist eng (Sie müssen ziemlich viel auf Minute), es funktioniert besser als die einfache Antwort, die abzufragen und zu starten ist, was in der letzte Minute. Es hilft auch, Sie in gewissem Maße von Skalierungsproblemen zu isolieren - das Abrufen einer Menge von Statusinformationen, um herauszufinden, was ausgeführt werden soll, könnte dazu führen, dass Sie Aufgaben verpassen. Es gibt viele Falten, und es hängt wirklich von der Dienstleistung ab, die Sie garantieren möchten. –

+0

Ok, nach einigem Nachdenken, gehe ich mit :) – Oxymoron

0

SQL Agent scheint eine gute Wahl zu sein, aber Sie erhalten kein Feedback zur Client-App.

0

Was wäre, wenn Sie eine Timer-Instanz als Teil der Datenstruktur hätten, und planen Sie, dass sie einmal ausgeführt wird, wenn diese Aktion fällig ist. Auf diese Weise müssen Sie nicht prüfen, und sobald Sie Ihre Struktur in die Warteschlange oder Liste setzen, wissen Sie, dass sie ausgeführt werden soll. der Timer auf einem separaten Thread Feuer, und so wird Ihr Code Asynchron zum Teil ausführen, die mit dem db spricht ...

+0

Bedeutet das, dass du einen Thread pro Aufgabe brauchst? Oder würde es ein bestimmtes Timing-Ereignis abonnieren und sich selbst abmelden, wenn die Ereignisdaten zum richtigen Zeitpunkt wären? z.B. Sie haben einen einzelnen Timer-Thread, der jede Minute oder so lange Timing-Ereignisse aussendet, und die Tasks registrieren sich, um diese Ereignisse zu empfangen. –

1

Eine vorhandene Lösung ...

http://quartznet.sourceforge.net/

+0

würde ich, aber nicht/nicht erlaubt. – Oxymoron

+0

+1, wie usnig etwas bereits vorhanden ist eine gute Idee :) –

+0

@ Oxymoron: Ich würde hier für eine Ausnahme kämpfen. Mit einer vorhandenen Lösung müssen Sie nur einen Adapter erstellen, um den bereits vorhandenen Datenspeicher und den Scheduler zu verknüpfen. –