Benutzer trifft Seite spawn.aspx die dann ein halbes Dutzend Themen laicht, Rendering Seiten alle mitmithilfe eines Httpcontext über Threads
((System.Web.IHttpHandler)instance).ProcessRequest(reference to spawn's HTTPContext);
nicht über die Tatsache Sorgen Sie sich, dass ASP.Net scheinbar den Benutzer sendet 7 Antworten für 1 Anfrage, dieser Teil wird bearbeitet und nur eine Antwort wird gesendet.
Das Problem ist, in einer stark frequentierten Umgebung (unsere Produktionsumgebung) mit vielen Threads (Quad-Quads) erhalten wir einen Fehler:
System.IndexOutOfRangeException at System.collections.ArrayList.Add at System.Web.ResponseDependencyList.AddDependencies(String[] items, String argname, Boolean cloneArray, DateTime utcDepTime) at System.Web.ResponseDependencyList.AddDependencies(String[] items, String argname, Boolean cloneArray, String requestVritualPath) at System.Web.UI.Page.AddWrappedFileDependencies(Object virtualFileDependencies) at ASP.spawned_page_no_1_aspx.FrameworkInitialize() at System.Web.UI.Page.ProcessRequest
Wir können nicht an andere Stelle kopieren. Mein Kollege glaubt, dass dies daran liegt, dass ich den ursprünglichen HTTPContext wiederverwende und ihn an die anderen Threads weitergebe, und dass er nicht Thread-sicher ist.
Nach dieser Logik habe ich versucht, einen neuen HTTPContext zu erstellen, um in die Threads zu gelangen. Aber Teile davon scheinen sich nicht zu "vereinigen". Insbesondere muss ich das Session-Objekt in den neuen HTTPContext holen. Ich kann mir vorstellen, dass ich auch andere Teile einbauen möchte, wie Cache. Für den Datensatz HTTPContext.Current.Session.IsSynchronized ist false.
Meine Fragen sind:
- Glauben Sie, der Fehler von der Verwendung Httpcontext über Threads ist?
- Wie kann ich es beheben?
- Wenn der Fix den HTTPContext für jeden Thread dupliziert, wie kann ich die Session (und Cache) in den neuen bekommen? Request und Response kommen im ctor, aber Session ist nicht einstellbar.
Edit: Details
Also auf diese Aussage zurück: „Seien Sie nicht über die Tatsache Sorgen, dass ASP.Net scheinbar wird der Benutzer 7 Antworten für 1-Anforderung sendet, wird dieser Teil behandelt und nur eine Antwort wird gesendet. " Riesiger Fan von Raymond Chen, ich stimme Ihnen zu: "Jetzt haben Sie zwei Probleme" ist eine sinnvolle Aussage in Ermangelung weiterer Informationen.
Was tatsächlich passiert ist, dass ich ein Excel-Dokument erstellen, um zurück zu senden. Auf der Seite spawn.aspx werden einige Statusinformationen erstellt, einschließlich der Tatsache, dass das Rendering in Excel ausgeführt wird, und des Objekts, für das das Rendering ausgeführt werden soll. Jede erstellte Seite erhält diese Informationen und blockiert so lange, bis sie an das Objekt gerendert werden. Wenn wahrsten Sinne des Wortes wie folgt aussieht:
protected override void Render(System.Web.UI.HtmlTextWriter writer)
{
if (this.RenderToExcel)
{
Deadlocker.SpinUntilCurrent(DeadLockToken);
RenderReport(this, this.XLSWriter);
Deadlocker.Remove(DeadLockToken);
}
else
base.Render(writer);
}
Aber alle die Verarbeitung bis zu diesem Punkt - Datenbankzugriff, Kontrolle Hierarchie, alles, was parallel durchgeführt. Und es gibt eine Menge davon - genug, um es zu parrallisieren, während es Render noch blockieren lässt, wird die Gesamtzeit in mehr als der Hälfte reduzieren.
Und der beste Teil davon ist - nichts musste für den Excel-Render neu geschrieben werden. Alle Steuerelemente wissen, wie man sich selbst übertrifft, und Sie können jede erzeugte Seite unabhängig besuchen (das ist der "normale Fall" tatsächlich - der Excel-Bericht ist nur eine Ansammlung aller erzeugten Seiten.)
Also dachte ich mir das Das Endergebnis würde lauten: "Du kannst das nicht, du musst den Ansatz überdenken" - aber ich musste es zumindest versuchen, weil alles so gut funktioniert, ohne Logik oder Code zu kopieren oder etwas zu abstrahieren ist einfach so perfekt. Und es ist nur Multi-Threading, das ist das Problem, wenn ich die Seiten seriell rendern alles ist in Ordnung, nur langsam.
Al diese Sperre wird wahrscheinlich schwer zu arrangieren, die Threading-Ausnahme, die er bekommt, ist von der Klasse Page, die den HTTP-Kontext mutiert, es sei denn, er kann die Aktion in der Seite, die dies tut, überschreiben und eine Sperre dann die Verriegelungslösung wird nicht funktionieren. – meandmycode
Großartiger Kommentar, ich stimme dir zu. Meine Präferenz wäre, ein völlig neues Objekt zu übergeben, das einige seiner Informationen aus dem HTTP-Kontext zum Zeitpunkt der Profilerstellung ableitet. Das wäre kugelsicher. –