Zunächst einige Gedanken zum Hintergrund:
1) Da es sich um einen lang laufenden Auftrag handelt, möchten Sie vielleicht einen Zwischenspeicher mit bereits ausgeführten Aufträgen einrichten, um doppelte Arbeit und eine Überlastung des Servers zu vermeiden.
2) Sie sollten keinen separaten Hintergrund-Thread starten müssen, da jede ASP.NET-Anfrage ohnehin in einem eigenen Thread ausgeführt wird. Wenn Sie jedoch feststellen, dass Sie Ihren ASP.NET-Arbeitsprozess aushungern, können Sie Ihre Webmethoden auf der Serverseite asynchron machen - siehe: dieser Artikel .
Die Implementierung erfordert drei Komponenten - einen Cache, eine Webmethode zur Ausführung des Auftrags und eine Webmethode zur Überprüfung des Auftragsstatus. Außerdem müssen Sie in der Lage sein, einen Schlüssel zu generieren, mit dem das System die Anfragen verfolgen kann. Sie können diesen Schlüssel serverseitig (bei der Generierung der Seite) oder clientseitig (wenn Sie einen cleveren Algorithmus haben, der eindeutige IDs erzeugen kann) erzeugen.
Der Cache kann anwendungsspezifisch sein, wenn Sie möchten, dass Benutzer laufende Aufträge gemeinsam nutzen können, oder sitzungsspezifisch, wenn Sie dies nicht wünschen. Der Cache ist einfach ein Wörterbuch, das Verweise auf Ihre laufenden Auftragsinstanzen enthält.
Ein einfaches Beispiel (es lässt sich nicht kompilieren, enthält wahrscheinlich Syntaxfehler und dient hauptsächlich dazu, den Sinn der Sache zu verdeutlichen).
Server-Pseudocode:
//In application Session_Start,
Session["ReportCache"] = new Dictionary<string, ReportStatus>();
public class ReportResults
{
}
public class ReportStatus
{
public int PercentComplete = 0;
}
[WebMethod(EnableSessions = true)]
ReportResults RunReport(string uniqueid)
{
ReportStatus status = new ReportStatus();
Session["ReportStatus"].Add(uniqueid, status);
//Start report
for(int i = 0; i < 100000; ++i)
{
//update the report status
status.PercentComplete = 100 * 100000 * i / 100000;
}
Session["ReportStatus"].Remove(uniqueid);
}
[WebMethod(EnableSessions=true)]
public ReportStatus GetStatus(uniqueid)
{
try
{
return Session["ReportStatus"][uniqueid];
}
catch(Exception)
{
return null;
}
}
Verwenden Sie auf dem Client Ajax, um die erste Webmethode aufzurufen. Der onSuccess-Callback wird erst dann aufgerufen, wenn der Bericht fertig ist. Verwenden Sie setTimeout, um die zweite Webmethode regelmäßig abzufragen, um Statusinformationen zu erhalten und den Client zu aktualisieren. Wenn die erste Web-Methode abgeschlossen ist, brechen Sie den Timer ab.
Ihr größtes Problem wird die Tatsache sein, dass Ihr Server viele lang laufende Aufträge ausführt, was die Gesamtleistung und Reaktionsfähigkeit beeinträchtigen kann. Vielleicht sollten Sie einen ganz anderen Ansatz wählen. Anstatt die Berichte bei Bedarf pro Benutzer auszuführen, können Sie beispielsweise die Liste der Personen, die den Bericht erhalten möchten, in eine Warteschlange stellen.