2012-09-30 6 views
20

Cercando di utilizzare il nuovo modello asincrono C# 5 è stato sorprendente per me AspNetSynchronizationContext è una classe interna (così come la base AspNetSynchronizationContextBase). Così senza documenti. Ma è essenziale sapere cosa fa quando si utilizza la funzione asincrona/attesa nel codice ASP.NET. Ho corretto che garantisce che le vostre continuazioni otterranno lo stesso HttpContext.Current come chiamanti originali? E 'non garantire che le continuazioni vengano eseguite sullo stesso thread dei chiamanti?AspNetSynchronizationContext

Se quest'ultima ipotesi non è vera e ottengo il thread originale posso essere sicuro di ottenere lo stesso contesto di thread in continuazioni? Intendo principal/culture associate al thread e thread storage locale? Questo è importante perché la localizzazione di ASP.NET si basa sulla cultura dei thread e la mia applicazione si basa sul modello di sicurezza dei ruoli .NET (principale del thread).

risposta

21

Sono corretto che garantisce che le vostre continuazioni otterranno lo stesso HttpContext.Current come chiamanti originali? Non garantisce che le continuazioni vengano eseguite sullo stesso thread dei chiamanti?

Sì, HttpContext.Current viene conservato e sì, le continuazioni possono essere eseguite su un thread diverso.

Intendo principal/culture associate alla memoria locale thread e thread? Questo è importante perché la localizzazione di ASP.NET si basa sulla cultura dei thread e la mia applicazione si basa sul modello di sicurezza dei ruoli .NET (principale del thread).

L'archiviazione locale di thread ordinaria è persa. È possibile attenuarlo utilizzando LogicalCallContext (che scorre con ExecutionContext), ma con async è più semplice fare semplicemente riferimento alle variabili direttamente.

Il preside è sempre conservato; fare altrimenti sarebbe un rischio per la sicurezza. Questo scorre con ExecutionContext.

Credo che la cultura fluisca con AspNetSynchronizationContext, ma non l'ho ancora testato su .NET 4.5's new implementation.


È possibile trovare il mio MSDN article on SynchronizationContext utile. Non è documentazione ufficiale (non lavoro per Microsoft), ma almeno è qualcosa. Si noti che il numero AspNetSynchronizationContext a cui si fa riferimento in questo articolo viene ora chiamato LegacyAspNetSynchronizationContext in .NET 4.5.

Un'altra grande risorsa è ExecutionContext vs. SynchronizationContext di Stephen Toub.

+0

Ottima risposta! Esattamente quello che volevo sentire più alcuni link utili. Grazie mille! – UserControl

+0

Suppongo che 'AspNetSynchronizationContext' si comporta in modo un po 'strano quando si tratta di' Thread.CurrentPrincipal': http://stackoverflow.com/a/12030785/463785 sai se questo è l'errore di 'AspNetSynchronizationContext' o alcuni altre cose di livello ASP.NET? – tugberk

+0

Non posso dire per certo. È possibile che il contesto di base .NET ('ExecutionContext') abbia alcune regole speciali per' CurrentPrincipal' (per ragioni di sicurezza) e ASP.NET non può superare questo (ad esempio in uno scenario di fiducia parziale). Ma questa è solo una congettura. –

4

Bene, mentre l'acquisizione di ExecutionContext è sempre garantita, l'acquisizione e l'esecuzione dell'esecuzione sullo stesso SynchronizationContext dipende dall'Adverter.

Il waiter più comune (il tipo restituito dal metodo GetAwaiter() chiamato internamente quando si "attende" qualcosa) è TaskAwaiter restituito da Task.GetAwaiter(). Per impostazione predefinita, TaskAwaiter acquisirà il SynchronizationContext corrente ed eseguirà il delegato di continuazione sul SynchronizationContext catturato. Il che significa che sarai in grado di utilizzare HttpContext.Current nel resto del tuo metodo e non ti dispiace che venga eseguito come una continuazione. Quindi, questo codice funziona come previsto (la parte in cui si scrive "B" verrà eseguito sullo stesso SynchronizationContext come la prima linea):

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

È possibile modificare questo comportamento utilizzando Task.ConfigureAwait(false) metodo, che racconta l'awaiter per non eseguire il marshalling del resto del metodo sul SynchronizationContext originale.

Ovviamente, se si utilizza Task.Run o Task.Factory.StartNew nel metodo asincrono che si sta chiamando, è responsabilità dell'utente acquisire nuovamente SynchronizationContext.

Buona fortuna.

+0

Sì, ma penso che non sia quello che chiede la domanda. Si chiede cosa accade specificamente in ASP.NET se si * fa * catturare il contesto. – svick

+0

quindi sicuro, hai tutto ... questa è la definizione del contesto. si applica sia a ExecutionContext (che viene comunque acquisito) sia a SynchronizationContext (che in realtà fa parte di ExceutionContext, ma può essere catturato e non può essere catturato). –