C # 5 .NET MVC lange asynchrone Aufgabe, Fortschrittsbericht und global abbrechen

8

Ich benutze ASP.Net MVC 5 und ich habe eine lange laufende Aktion, die Webservices abfragen, Daten verarbeiten und in der Datenbank speichern muss.

Dafür möchte ich die TPL-Bibliothek verwenden, um die Aufgabe async zu starten.

Aber ich frage mich, wie man drei Sachen macht:

  • Ich möchte den Fortschritt dieser Aufgabe melden. Dafür denke ich an SignalR
  • Ich möchte in der Lage sein, die Seite, von der ich diese Aufgabe aus starte, verlassen zu können und den Fortschritt über die Website melden zu können (von einem Panel auf der linken Seite, aber das ist ok)
  • Und ich möchte diese Aufgabe global abbrechen können (in meinem Panel links)

Ich kenne eine ganze Menge über alle beteiligten Technologien. Aber ich bin nicht sicher über den besten Weg, dies zu erreichen.

Kann mir jemand die beste Lösung anbieten?

    
Dragouf 28.10.2013, 16:57
quelle

2 Antworten

9

Die Tatsache, dass Sie eine lang andauernde Arbeit ausführen möchten, während der Benutzer von der Seite weggehen kann, die die Arbeit initiiert, bedeutet, dass Sie diese Arbeit "im Hintergrund" ausführen müssen. Es kann nicht als Teil einer regulären HTTP-Anfrage ausgeführt werden, da der Benutzer seine Anfrage jederzeit abbrechen kann, indem er weg navigiert oder den Browser schließt. In der Tat scheint dies ein Schlüsselszenario für Sie zu sein.

Hintergrundarbeit in ASP.NET ist gefährlich. Sie können es sicherlich abziehen, aber es ist nicht einfach, richtig zu machen. Außerdem können Worker-Prozesse aus vielen Gründen beendet werden (App-Pool-Recycling, Bereitstellung, Neustart des Computers, Maschinenfehler, Stack Overflow oder OOM-Ausnahme bei einem nicht verwandten Thread). Achten Sie also darauf, dass Ihre langwierige Arbeit in der Mitte abgebrochen wird. Sie können die Wahrscheinlichkeit verringern, dass dies geschieht, aber niemals die Möglichkeit ausschließen.

Sie können Ihren Code angesichts einer willkürlichen Beendigung schützen, indem Sie alle Arbeiten in einer Transaktion einschließen. Dies funktioniert natürlich nur, wenn Sie keine nicht-abgeschlossenen Nebenwirkungen wie Web-Service-Aufrufe verursachen, die den Status ändern. Es ist nicht möglich, hier eine allgemeine Antwort zu geben, da die Sicherheit bei willkürlichen Beendigungen in hohem Maße von der konkreten Arbeit abhängt.

Hier ist eine mögliche Architektur, die ich in der Vergangenheit benutzt habe:

  • Wenn ein Job eingeht, schreiben Sie alle notwendigen Eingabedaten in eine Datenbanktabelle und melden dem Client Erfolg.
  • Sie müssen einen Weg finden, um einen Mitarbeiter für die Arbeit an diesem Job zu starten. Sie könnten sofort eine Aufgabe starten. Sie benötigen außerdem eine periodische Prüfung, die nach nicht gestarteten Aufgaben sucht, falls die App nach dem Hinzufügen des Arbeitselements, aber vor dem Starten einer Aufgabe, beendet wird. Lassen Sie den Windows Taskplaner in Ihrer App einmal pro Minute eine geheime URL aufrufen.
  • Wenn Sie anfangen, an einem Job zu arbeiten, markieren Sie diesen Job so, dass er ausgeführt wird, damit er nicht versehentlich ein zweites Mal aufgerufen wird. Arbeiten Sie an diesem Job, schreiben Sie die Ergebnisse und markieren Sie es als erledigt. Alles in einer einzigen Transaktion. Wenn Ihr Prozess in der Mitte beendet wird, setzt die Datenbank alle beteiligten Daten zurück.
  • Schreiben Sie den Jobfortschritt in eine separate Tabellenzeile in einer separaten Verbindung und separater Transaktion. Der Browser kann den Server nach Fortschrittsinformationen abfragen. Sie könnten SignalR auch verwenden, aber ich habe keine Erfahrung damit, und ich erwarte, dass es schwierig sein würde, die Fortschrittsmeldung bei willkürlicher Beendigung wieder aufzunehmen.
  • Die Löschung würde durch Setzen eines Abbruch-Flags in der Fortschrittsinformationszeile erfolgen. Die App muss diese Flagge abfragen.

Vielleicht können Sie Message Queuing für die Jobverarbeitung verwenden, aber ich bin immer vorsichtig, es zu verwenden. Um eine Nachricht in einer abgewickelten Weise zu verarbeiten, benötigen Sie MSDTC, das mit vielen Hochverfügbarkeitslösungen für SQL Server nicht unterstützt wird.

Man könnte meinen, dass diese Architektur nicht sehr anspruchsvoll ist. Es nutzt die Abfrage für viele Dinge. Polling ist eine primitive Technik, aber es funktioniert ganz gut. Es ist zuverlässig und gut verstanden. Es hat ein einfaches Nebenläufigkeitsmodell.

Wenn Sie annehmen können, dass Ihre Anwendung zu unpassenden Zeiten nie beendet wird, wäre die Architektur viel einfacher. Aber das kann nicht angenommen werden. Sie können nicht davon ausgehen, dass es während der Arbeitszeit keine Bereitstellungen geben wird und keine Bugs zu Abstürzen führen werden.

    
usr 28.05.2014, 13:20
quelle
7

Auch wenn die Verwendung von http-Worker eine schlechte Sache ist, um eine lange Aufgabe auszuführen, habe ich ein kleines Beispiel dafür gemacht, wie man es mit SignalR verwaltet:

In diesem Beispiel können Sie:

  • Starten Sie eine Aufgabe
  • Siehe Aufgabenfortschritt
  • Aufgabe abbrechen

Es basiert auf:

  • twitter bootstrap
  • knockoutjs
  • signalR
  • C # 5.0 async / wartet mit CancelToken und IProgress
  • auf

Sie können die Quelle dieses Beispiels hier finden:

Ссылка

    
Dragouf 02.06.2014 11:05
quelle