Pytanie AspNetSynchronizationContext


Próba użycia nowego asynchronicznego modelu C # 5 zaskoczyła mnie AspNetSynchronizationContext jest klasą wewnętrzną (jak również AspNetSynchronizationContextBase baza). Tak więc nieudokumentowane. Ale ważne jest, aby wiedzieć, co robi, wykorzystując funkcję async / await w kodzie ASP.NET. Czy to poprawiam? To robi zagwarantować, że twoje kontynuacje będą takie same HttpContext.Current jako oryginalni rozmówcy? To nie zagwarantować, że kontynuacje będą wykonywane w tym samym wątku, co osoby dzwoniące?

Jeśli to drugie założenie nie jest prawdą i otrzymam oryginalny wątek, czy mogę uzyskać ten sam kontekst wątku w kontynuacjach? Mam na myśli główny / kulturę związaną z lokalnym magazynem wątków i wątków? Jest to ważne, ponieważ lokalizacja ASP.NET opiera się na kulturze wątku, a moja aplikacja opiera się na modelu bezpieczeństwa roli .NET (główny wątek).


21
2017-09-30 08:31


pochodzenie


Wiem tylko, że po wznowieniu połączenia po oczekującej rozmowie, niezależnie od otrzymywanego wątku, jego "Nazwa" zostaje zresetowana do zera. Po powrocie do puli jest wyczyszczone. Jeśli chodzi o inne właściwości związane z wątkiem ... nie wiem. - Triynko


Odpowiedzi:


Czy mam rację, że to gwarantuje, że twoje kontynuacje otrzymają ten sam HttpContext.Current jako oryginalny rozmówca? Nie gwarantuje to, że kontynuacje będą wykonywane w tym samym wątku, co osoby dzwoniące?

Tak, HttpContext.Current jest zachowany, i tak, kontynuacje mogą być wykonywane na innym wątku.

Mam na myśli główny / kulturę związaną z lokalnym magazynem wątków i wątków? Jest to ważne, ponieważ lokalizacja ASP.NET opiera się na kulturze wątku, a moja aplikacja opiera się na modelu bezpieczeństwa roli .NET (główny wątek).

Zwykła pamięć lokalna wątku jest tracona. Możesz to złagodzić, używając LogicalCallContext (który płynie z ExecutionContext), ale z async łatwiej jest po prostu odwoływać się bezpośrednio do zmiennych.

Główny jest zawsze zachowany; w przeciwnym razie stanowiłoby zagrożenie dla bezpieczeństwa. To płynie z ExecutionContext.

Wierzę, że kultura płynie z AspNetSynchronizationContext, ale nie testowałem tego Nowa implementacja .NET 4.5.


Możesz znaleźć moje Artykuł MSDN na temat SynchronizationContext pomocny. To nie jest oficjalna dokumentacja (nie pracuję dla Microsoftu), ale przynajmniej to jest coś. Zauważ, że AspNetSynchronizationContext wymienione w tym artykule jest teraz wywoływane LegacyAspNetSynchronizationContext w .NET 4.5.

Kolejnym świetnym źródłem jest Stephen Toub ExecutionContext vs. SynchronizationContext.


23
2017-09-30 12:28



Świetna odpowiedź! Dokładnie to, co chciałem usłyszeć plus kilka użytecznych linków. Dziękuję Ci bardzo! - UserControl
Zakładam to AspNetSynchronizationContext zachowuje się nieco dziwnie, jeśli chodzi o Thread.CurrentPrincipal: stackoverflow.com/a/12030785/463785 czy wiesz, czy to wina winy AspNetSynchronizationContext lub jakiś inny głęboki poziom ASP.NET? - tugberk
Nie mogę powiedzieć na pewno. Możliwe, że podstawowy kontekst .NET (ExecutionContext) ma specjalne zasady dla CurrentPrincipal (ze względów bezpieczeństwa), a program ASP.NET nie może tego obejść (na przykład w scenariuszu częściowego zaufania). Ale to tylko przypuszczenia. - Stephen Cleary


Cóż, podczas przechwytywania ExecutionContext jest zawsze gwarantowane, przechwytywanie i uruchamianie wykonywania w tym samym SynchronizationContext zależy od Awaiter.

Najczęstszym awaiterem (typ zwracany przez metodę GetAwaiter () wewnętrznie wywoływaną podczas "oczekiwania") jest TaskAwaiter, który został zwrócony przez Task.GetAwaiter (). Domyślnie TaskAwaiter przechwyci bieżący kontekst synchronizacji i uruchom delegację kontynuacji na przechwyconym obiekcie SynchronizationContext. Oznacza to, że będziesz mógł użyć HttpContext.Current w pozostałej części metody i nie masz nic przeciwko temu, że będzie działał jako kontynuacja. Tak więc ten kod będzie działać zgodnie z oczekiwaniami (część, w której piszesz "B", będzie działać na tym samym tekście synchronizacji co pierwsza linia):

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

Możesz zmienić to zachowanie, używając Task.ConfigureAwait(false) metoda, która nakazuje awatarowi, aby nie doprowadził reszty metody do pierwotnego stanu synchronizacji.

Oczywiście, jeśli używasz Task.Run lub Task.Factory.StartNew w metodzie asynchronizacji, którą wywołujesz, to Ty jesteś odpowiedzialny za ponowne przechwycenie SynchronizationContext.

Powodzenia.


4
2017-09-30 09:28



Tak, ale myślę, że nie o to pyta. Pyta, co konkretnie dzieje się w ASP.NET, jeśli ty zrobić uchwycić kontekst. - svick
to jasne, masz wszystko ... to jest definicja kontekstu. ma zastosowanie zarówno do Kontekstu Wykonania (który został przechwycony w każdym razie), jak i do Kontekstu Synchronizacji (który jest faktycznie częścią KontekstuKontekstu, ale może zostać przechwycony i nie może zostać przechwycony). - Shahar Gvirtz