Wie pausiere ich während der Ausführung, speichere den Zustand und fahre später am selben Punkt fort?

9

Ich habe einen Thread, der etwas verarbeitet. Ich möchte in der Lage sein, diesen Thread während der Ausführung zu stoppen, irgendwie seine Position (und den Zustand der Objekte, auf denen er arbeitet) zu speichern und dann von diesem Ort zu einem späteren Zeitpunkt fortzufahren (also nachdem mein Computer neu gestartet wurde).

In C # ist das nicht möglich, oder? Und wenn nicht, was ist das richtige Design, um diese Funktionalität zu erreichen?

Also war mein ursprünglicher Wunsch, etwas wie

zu haben %Vor%

und in der Lage sein zu pausieren / speichern an jedem Punkt innerhalb dieser Funktion. Wenn die Funktion endet, weiß jeder, dass sie vollständig ist. Als eine Alternative, vielleicht ist dies der bessere Weg, es zu tun

%Vor%

Der erste Fall ist also viel einfacher für andere Leute, die meine Basisklasse erben müssen, da sie nur die Execute-Funktion implementieren müssen. Im zweiten Fall müssen sie jedoch den vorherigen Zustand berücksichtigen und auch festlegen, wo gute Pausepunkte existieren. Gibt es einen besseren Weg, dies zu tun?

    
i8abug 03.11.2011, 14:41
quelle

5 Antworten

4

Was Sie wollen, könnte von einer serialisierbaren Zustandsmaschine erreicht werden. Im Grunde ändern Sie Ihre lokalen Variablen in Felder in einer Klasse und fügen ein Feld hinzu, das den Status behält - die Position im Code der ursprünglichen Methode. Diese Klasse wird [Serializable] und es wird eine Methode wie MoveNext() geben, die eine Arbeit macht und zurückgibt. Wenn Sie arbeiten, rufen Sie diese Methode in einer Schleife auf. Wenn Sie anhalten möchten, warten Sie, bis der aktuelle Anruf beendet ist, brechen Sie die Schleife ab und serialisieren Sie den Zustandsautomaten auf dem Datenträger.

Basierend auf der Komplexität der ursprünglichen Methode und wie oft Sie "checkpoint" möchten (wenn die Methode MoveNext() zurückkehrt und Sie können fortfahren oder nicht), könnte die Zustandsmaschine so einfach sein wie nur eine Zustand oder ziemlich kompliziert.

Der C # -Compiler führt eine sehr ähnliche Transformation durch, wenn Iteratorblöcke kompiliert werden (und die async -Methoden von C # 5). Aber es ist nicht für diesen Zweck gedacht und markiert nicht die generierte Klasse [Serializable] , also glaube ich nicht, dass du sie benutzen könntest. Obwohl das Lesen einiger Artikel darüber, wie diese Transformation tatsächlich durchgeführt wird, Ihnen helfen könnte, das gleiche selbst zu tun.

    
svick 03.11.2011, 16:00
quelle
1

Dies kann leicht mit WF erreicht werden ... es hat alle Rohrleitungen, um Aufgaben explizit anzuhalten und fortzusetzen (und es kümmert sich um die Persistenz für Sie). Sehen Sie sich diesen Link an.

Wahrscheinlich nicht geeignet für das, was Sie wollen, aber vielleicht eine Untersuchung wert.

    
Mike Hanrahan 03.11.2011 16:09
quelle
0

Ich kann nicht für C# antworten, aber im Allgemeinen heißt diese Frage Persistenz und es gibt keine einfache allgemeine Lösung (außer die Sprache und das System bieten es). Sie können nicht in einem Thread argumentieren, weil der Thread, den Sie in Betracht ziehen, auf andere (globale oder Heap-) Daten verweist. Diese Frage bezieht sich auch auf die Garbage-Collection (weil sowohl Garbage Collectors als auch Persistency-Mechanismen dazu neigen, das gesamte Leben zu scannen Heap).

    
Basile Starynkevitch 03.11.2011 14:48
quelle
0

Sie könnten so etwas mit einem Ausdrucksbaum oder einer Methodenkette einrichten. Richten Sie Lambdas oder kleine Methoden für die kleinsten "atomaren" Arbeitseinheiten ein, die nicht unterbrochen werden können. Dann ketten Sie sie zusammen mit einem "Supervisor", der jeden dieser Brocken in der richtigen Reihenfolge ausführt, aber er kann sagen, dass er zwischen den Befehlen aufhört zu tun, seine Position entlang der Kette speichert, zurückkehrt und darauf wartet, wieder aufgenommen zu werden. Wenn Sie den Namen eines Musters wollten, könnten Sie es als Variation des Visitors bezeichnen.

    
KeithS 03.11.2011 14:50
quelle
0

Sie möchten den Status Ihres Objekts serialisieren, wenn der Prozess pausiert ist, und ihn nach dem Neustart deserialisieren.

Eine sehr naive Implementierung wäre, zwei statische Methoden für Ihre Task-Klasse Serialize / Deserialize zu erstellen, die Linq verwenden, um den Zustand Ihres Objekts in XML zu lesen / schreiben. Wenn eine Task pausiert ist, rufen Sie Serialize auf, das das Objekt als XML auf die Festplatte ablegt. Wenn es neu gestartet wird, rufen Sie Deserialize auf, das das XML liest. Es gibt auch die XmlSerializer Klasse, die robuster sein kann.

Ungeachtet dessen ist dies ein komplexes Problem mit einer konzeptionell einfachen Lösung.

    
Jason 03.11.2011 14:51
quelle

Tags und Links