2012-09-30 4 views
20

Der Versuch, neue C# 5 Async-Modell verwenden, war es überraschend für mich AspNetSynchronizationContext ist eine interne Klasse (sowie AspNetSynchronizationContextBase Basis). So undokumentiert. Aber es ist wichtig zu wissen, was es tut, wenn async/await-Funktion in Ihrem ASP.NET-Code verwendet wird. Bin ich richtig, dass Es tut Ihre Fortsetzungen garantieren die gleiche HttpContext.Current als ursprüngliche Anrufer erhalten? Es nicht garantieren die Fortsetzungen werden auf dem gleichen Thread wie die Anrufer ausgeführt werden?AspNetSynchronizationContext

Wenn diese Annahme nicht wahr ist, und ich bekomme das ursprüngliche Thread kann ich sicher sein, den gleichen Thread-Kontext in Fortsetzungen zu bekommen? Ich meine Principal/Kultur mit dem Thread und lokalen Thread-Speicher verbunden? Das ist wichtig, weil die Lokalisierung von ASP.NET von der Kultur des Threads abhängt und meine Anwendung auf dem .NET-Rollensicherheitsmodell (dem Prinzip des Threads) beruht.

Antwort

21

Bin ich richtig, dass es Ihre Fortsetzungen garantiert die gleiche HttpContext.Current als ursprüngliche Anrufer erhalten? Es garantiert nicht, dass die Fortsetzungen auf demselben Thread wie die Anrufer ausgeführt werden?

Ja, HttpContext.Current ist erhalten, und ja, die Fortsetzungen können auf einem anderen Thread ausgeführt werden.

ich meine Prinzipal/Kultur mit dem Thread und lokalen Thread-Speicher zugeordnet? Das ist wichtig, weil die Lokalisierung von ASP.NET von der Kultur des Threads abhängt und meine Anwendung auf dem .NET-Rollensicherheitsmodell (dem Prinzip des Threads) beruht.

Gewöhnlicher thread-lokaler Speicher ist verloren. Sie können dies abzumildern, indem LogicalCallContext mit (das fließt mit ExecutionContext), aber mit async ist es einfacher, nur direkt auf die Variablen zu verweisen.

Auftraggeber ist immer erhalten; etwas anderes zu tun wäre ein Sicherheitsrisiko. Dies fließt mit ExecutionContext.

Ich glaube, dass Kultur mit AspNetSynchronizationContext fließt, aber ich habe dies nicht auf .NET 4.5's new implementation getestet.


Sie können meine MSDN article on SynchronizationContext hilfreich finden. Es ist keine offizielle Dokumentation (ich arbeite nicht für Microsoft), aber es ist zumindest etwas. Beachten Sie, dass die AspNetSynchronizationContext, auf die in diesem Artikel verwiesen wird, jetzt in .NET 4.5 LegacyAspNetSynchronizationContext aufgerufen wird.

Eine andere große Ressource ist Stephen Toub ExecutionContext vs. SynchronizationContext.

+0

Große Antwort! Genau das, was ich hören wollte, plus ein paar nützliche Links. Vielen Dank! – UserControl

+0

Ich gehe davon aus, dass "AspNetSynchronizationContext" ein wenig seltsam verhält, wenn es zu "Thread.CurrentPrincipal" kommt: http://StackOverflow.com/a/12030785/463785 wissen Sie, ob dies der Fehler "AspNetSynchronizationContext" oder etwas ist andere tiefe ASP.NET Sachen? – tugberk

+0

kann ich nicht sicher sagen. Es ist möglich, dass der Kern-.NET-Kontext ('ExecutionContext') einige spezielle Regeln für' CurrentPrincipal' hat (aus Sicherheitsgründen), und ASP.NET kann dies nicht überwinden (z. B. in einem Teil-Vertrauens-Szenario). Aber das ist nur Vermutung. –

4

Nun, während der ExecutionContext Erfassung immer gewährleistet ist, die Erfassung und die Ausführung auf dem gleichen SynchronizationContext auf dem Erwartenden hängt läuft.

Der am häufigsten verwendete Erwarter (der Typ, der von der Methode GetAwaiter() zurückgegeben wird, die intern aufgerufen wird, wenn Sie auf etwas warten), ist TaskAwaiter, der von Task.GetAwaiter() zurückgegeben wurde. Standardmäßig erfasst TaskAwaiter den aktuellen SynchronizationContext und führt den Fortsetzungsdelegaten für den erfassten SynchronizationContext aus. Das heißt, Sie können HttpContext.Current im Rest Ihrer Methode verwenden, und es macht Ihnen nichts aus, dass es als Fortsetzung ausgeführt wird. Also, dieser Code funktioniert wie erwartet (der Teil, wo Sie „B“ läuft auf dem gleichen SynchronizationContext wie die erste Zeile schreibt):

HttpContext.Current.Response.Write("A"); 
await Task.Delay(1000); 
HttpContext.Current.Response.Write("B") 

Sie dieses Verhalten durch die Verwendung Task.ConfigureAwait(false) Methode ändern kann, das erzählt die Erwartenden den Rest der Methode nicht zum ursprünglichen SynchronizationContext zurückverlagern.

Wenn Sie in der von Ihnen aufgerufenen asynchronen Methode Task.Run oder Task.Factory.StartNew verwenden, liegt es natürlich in Ihrer Verantwortung, den SynchronizationContext erneut zu erfassen.

Viel Glück.

+0

Ja, aber ich denke, das ist nicht, was die Frage fragt. Es fragt, was speziell in ASP.NET passiert, wenn Sie * den * Kontext erfassen. – svick

+0

dann sicher, du hast alles ... das ist die Definition des Kontextes. Dies gilt sowohl für den ExecutionContext (der sowieso erfasst wurde) als auch für den SynchronizationContext (der tatsächlich Teil des ExeutionContext ist, aber erfasst werden kann und nicht erfasst werden kann). –