Ich habe einen ASP.NET-Webservice, der einige schwere Aufgaben erledigt, wie zum Beispiel einige Dateioperationen, oder die Erstellung von Excel-Tabellen aus einer Reihe von Crystal-Reports-Berichten. Ich möchte nicht blockiert werden, indem ich diesen Web-Service anrufe, also möchte ich den Web-Service-Aufruf asynchron machen. Außerdem möchte ich diesen Webservice von einer Webseite aufrufen und möchte einen Mechanismus, der es mir ermöglicht, den Server weiter zu überprüfen, so dass ich einen Indikator für den Fortschritt auf dem Bildschirm anzeigen kann, wie zum Beispiel die Anzahl der Dateien, die wurden bearbeitet. Bitte beachten Sie, dass ich nach Abschluss des Web-Methoden-Aufrufs keine Benachrichtigung möchte, sondern einen Live-Fortschrittsstatus. Wie gehe ich vor?Wie messen Sie den Fortschritt eines Web-Service-Anrufs?
Antwort
Schreiben Sie eine separate Methode auf den Server, die Sie abfragen können, indem Sie die ID des geplanten Jobs übergeben und einen ungefähren Wert zwischen 0-100 (oder 0.0 und 1.0, oder was auch immer) zurückgeben ist.
z. Im REST-Stil könnten Sie eine GET-Anfrage an http://yourserver.com/app/jobstatus/4133/
senden, die eine einfache '52' als text/plain
zurückgeben würde. Dann müssen Sie das nur abfragen (Sekunden? Zwei Sekunden? Zehn Sekunden?), Um zu sehen, wie weit es ist.
Wie Sie tatsächlich die Überwachung auf dem Backend erreichen, hängt sehr davon ab, was Ihr Prozess ist und wie er funktioniert.
Lassen Sie den ersten Web-Service-Aufruf "Startberichtgenerierung" eine Aufgabe in einem Aufgabenpool erstellen und geben Sie dem Anrufer die ID der Aufgabe zurück.
Geben Sie dann eine andere Methode an, die das "Prozent erledigt" für eine bestimmte taskId zurückgibt.
Stellen Sie eine dritte Methode bereit, die das tatsächliche Ergebnis für eine abgeschlossene Aufgabe zurückgibt.
Am einfachsten wäre es, wenn der Webdienst ein Feld in einer Datenbank mit dem Fortschritt des Aufrufs aktualisiert und dann einen Webdienst erstellt, der dieses Feld abfragt und den Wert zurückgibt.
Wenn Sie eine Datenbank verwenden, sollten Sie eine speicherinterne Tabelle erstellen. Es ist sinnlos, Festplatten-I/O bei trivialen Aufgaben zu verschwenden. –
Es muss nicht trivial sein, Sie könnten es als Audit/Log-Tabelle verwenden. Eine Spalte in der Tabelle könnte den oder Status speichern, andere könnten die Start-/Endzeiten, die Anrufer-ID und den Ergebniswert (fehlgeschlagen/erfolgreich usw.) speichern. – ilitirit
Lassen Sie den Web-Service eine Art Task-ID oder Sitzungs-ID zurückgeben. Erstellen Sie eine andere Webmethode für die Abfrage mit dieser ID, die die benötigten Informationen zurückgibt (% Completion, Liste der Dateien, was auch immer). Überprüfen Sie diese Methode in bestimmten Abständen vom Client.
Verwenden Sie eine Datenbank zum Speichern der Prozessinformationen. Wenn Sie dies im Speicher des Webdienstes tun, wird dies in der Webfarmumgebung nicht gut skalieren, da die Aufgabe möglicherweise auf einem anderen Server ausgeführt wird sind Polling.
EDIT: Ich habe gerade eine andere ähnliche Antwort gesehen und kommentieren. Der Kommentator hat Recht - Sie können die In-Memory-Tabelle verwenden, um Datenträgeroperationen zu vermeiden, aber immer noch einen separaten Datenbankserver zu verwenden.
denke ich, XML Web Service ist langsam, so dass mehrere Methoden und Polling der Fortschritt extrem langsam wird die Erstellung und wird große Last auf dem Server generieren. Ich würde es nicht in der Produktionsumgebung tun. Ich sehe die gleichen (aber kleinere) Probleme mit der Datenbankabfrage.
Versuchen Sie SOAP-Erweiterungen statt. Es implementiert ein ereignisgesteuertes Modell. Siehe Adding a Progress Bar to Your Web Service Client Application on MSDN.
Sie können auch use SoapExtensions benachrichtigen, um Ihren Kunden über den Download-/Prozessfortschritt zu informieren. Der Server kann dann Ereignisse an den Client senden. Nichts im Client muss geändert werden, wenn Sie es nicht verwenden.
Ermöglicht so etwas in Ihrem Client:
//...
private localhost.MyWebServiceService _myWebService = new localhost.MyWebServiceService();
_myWebService.processDelegate += ProgressUpdate;
_myWebService.CallHeavyMethod();
//...
private void ProgressUpdate(object sender, ProgressEventArgs e)
{
double progress = ((double)e.ProcessedSize/(double)e.TotalSize) * 100.00;
//Show Progress...
}
Und wir sind alle denken: „Warum nicht Web Services dies automatisch tun?“ Und das, was wir meinen, wenn wir sagen, dass sie saugen. Sie müssen all diese Sachen selbst bauen. –