2009-03-05 8 views
2

Dies ist eine mehrteilige Frage.ASP.NET HTTPHandlers und lange laufende Prozesse

Ich habe einen Prozess, der einige Minuten dauern kann, wird ausgeführt, indem ein HTTPHandler mit einer asynchronen Javascript-Anforderung aufgerufen wird.

Frage 1: Wie kann ich sicherstellen, dass diese Anfrage nicht auf dem Server und dem Client ausläuft?

Frage 2: Ist es möglich, Daten aus dem HTTPHandler während der Verarbeitung auszugeben, die zurück an das XmlHttpRequest-Objekt gesendet werden, bevor die letzte Seite abgeschlossen ist?

Ich möchte die tatsächliche Arbeitsbelastung berechnen und Prozentsatz zurückgeben. Ich schätze, dass das möglich ist.

Irgendwelche Tipps?

EDIT:

Ein schneller Test:

public void ProcessRequest(HttpContext context) 
    { 
     context.Response.ContentType = "text/plain"; 
     for (int i = 0; i < 100; i++) 
     { 
      context.Response.Write("Hello World " + i + Environment.NewLine); 
      System.Threading.Thread.Sleep(500); 
      context.Response.Flush(); 
     }    
    } 

Schiebt Hallo Welt Stück für Stück an den Client ... Das auf einem synchronious Anfrage funktioniert, sehe ich werde, wenn ein XMLHttpRequest ein Readystatechange bekommt Ereignis für jede Zeile.

Ich habe immer Multithreading in ASP.NET-Anwendungen vermeiden, weil Sie nicht kontrollieren können, wann der Arbeitsprozess stirbt, was dazu führen wird, dass alle seine erzeugten Threads sterben.

Stattdessen, warum einen separaten Thread-Pool neu erfinden, wenn IIS dies bereits für Sie vornimmt.

+0

Antwort auf neu zu erfinden einen Thread-Pool ... für lange laufenden Prozess nicht empfohlen, den Thread-Pool zu verwenden. http://msdn.microsoft.com/en-us/magazine/cc164128.aspx – Keltex

Antwort

1

Was ich in der Vergangenheit getan habe, ist den langwierigen Prozess für einen neuen Thread zu starten, und eine Eigenschaft für die Prozessklasse, die den% abgeschlossen angibt. Dann kann der Browser von Zeit zu Zeit einen AJAX-Aufruf an einen HttpHandler senden, der nur diese% complete -Eigenschaft abfragt. Auf diese Weise kehrt der HttpHandler sofort zurück.

Es kann Probleme geben, die berücksichtigt werden müssen, wenn der Job wichtig ist, z. B. die Abschwächung für den Worker-Prozess, um den Job zu recyceln oder den Status des Jobs zu speichern, damit er neu gestartet werden kann. Wenn der Job äußerst kritisch ist, ist es besser, einen Windows-Dienst zu schreiben, der den Job ausführt, und Remoting oder etwas zu verwenden, um den Fortschritt abzufragen.

0
  1. Sie können die Anforderung Timeout-Wert in web.config ändern, ungefähr wie: <configuration> <system.web><httpRuntime executionTimeout="1000" /></system.web></configuration>

  2. Soweit ich weiß, gibt es keine Möglichkeit, Informationen zurück derselben async Anfrage zu senden. Die meisten Ajax-Benutzerschnittstellen, die ich gesehen habe, erzeugen dieses Verhalten, indem sie eine statische Klasse haben, die die Statistiken für die laufenden Aufgaben enthält und dann diese mit einer anderen asynchronen Anfrage oder einem iframe abfragt. Ein gutes Beispiel für etwas Ähnliches ist die Neat Upload Control.

0

Hier ist eine Idee ...

Wenn Sie einen Prozess haben, die „mehrere Minuten“ zu verarbeiten, nimmt, könnte man am besten aus einem separaten Thread (oder separate Warteschlange von Threads) zu schaffen anstatt ASP.NET-Worker-Threads Dies liegt daran, dass der Webserver hängen bleibt, wenn Sie alle Worker-Threads verwenden. Weitere Informationen zu diesem Problem: http://msdn.microsoft.com/en-us/magazine/cc164128.aspx

Ihre erste AJAX-Anforderung wäre, den Prozess zu starten.Nachfolgende Aufrufe würden den Status des Prozesses einschließlich der% abgeschlossen erhalten. Verwenden Sie einen Timer, um abzufragen (alle paar Sekunden oder was auch immer am besten funktioniert), um die% abgeschlossen zu bekommen, bis alles fertig ist.

AJAX-Anfragen (XmlHttpRequest) haben keine Timeouts per se auf dem Client (http://luke.breuer.com/tutorial/xmlhttprequest.aspx ... scrollen Sie nach unten zu Timeouts), aber ich denke nicht, dass es eine gute Idee ist, sie für einige Minuten aus der Arbeit zu bringen wenn überhaupt möglich:

+0

Separate Threads leben noch im Worker-Prozess. –

+0

Ein Tippfehler, den ich korrigiert habe. – Keltex

0

HTTP-Anfragen per Definition sind staatenlos. Wie andere gezeigt haben - Sie können nicht vorhersagen, wann IIS den Prozess recyceln wird.

Der bessere Ansatz ist es, einen Windows-Dienst erstellen, um die eigentliche Arbeit und die Httphandler zu tun, oder Seite oder was auch immer es über den Fortschritt abzufragen und gibt diese an den Client. Sie können den Dienst auf demselben Computer installieren und dann Pipes oder einen anderen Remoting-Kanal verwenden, den Sie zwischen Ihrer Seite/Ihrem Handler und dem Dienst herstellen möchten.

0

Für das, was ihren Wert,

public void ProcessRequest(HttpContext context) 
{ 
    context.Response.ContentType = "text/plain"; 
    for (int i = 0; i < 100; i++) 
    { 
     context.Response.Write("Hello World " + i + Environment.NewLine); 
     System.Threading.Thread.Sleep(500); 
     context.Response.Flush(); 
    }    
} 

Und auf der Client-Seite:

httpObject.onreadystatechange = function() 
{ 
    // This is called whenever Flush() is called on the server. 
    // when readyState = 4, everything is done, but I can check responseText at anytime. 
} 

Works just fine.

+0

Das App-Pool-Recycling wird dies nicht beeinflussen? – ChadT

Verwandte Themen