Подтвердить что ты не робот

AspNetSynchronizationContext

Пытаясь использовать новую асинхронную модель С# 5, мне было удивительно, что AspNetSynchronizationContext является внутренним классом (а также базой AspNetSynchronizationContextBase). Таким образом, недокументировано. Но важно знать, что он делает, используя функцию async/await в вашем коде ASP.NET. Я исправлю это гарантирует, что ваши продолжения получат те же HttpContext.Current, что и исходные абоненты? Он не гарантирует, что продолжения будут выполняться в том же потоке, что и вызывающие?

Если последнее предположение неверно, и я получаю исходный поток, могу ли я получить тот же контекст потока в продолжениях? Я имею в виду главную/культуру, связанную с локальным хранилищем потоков и потоков? Это важно, потому что локализация ASP.NET основана на культуре потоков, и мое приложение использует модель безопасности роли .NET(директив потоков).

4b9b3361

Ответ 1

Я исправляю, что он гарантирует, что ваши продолжения получат тот же HttpContext.Current, что и исходные вызывающие? Это не гарантирует продолжения выполнения в том же потоке, что и вызывающие?

Да, HttpContext.Current сохраняется, и да, продолжения могут выполняться в другом потоке.

Я имею в виду главный/культ, связанный с локальным хранилищем потоков и потоков? Это важно, потому что локализация ASP.NET основана на культуре потоков, и мое приложение использует модель безопасности роли .NET(директив потоков).

Обычное локальное хранилище данных теряется. Вы можете уменьшить это, используя LogicalCallContext (который течет с помощью ExecutionContext), но с async проще просто ссылаться на переменные напрямую.

Принципал всегда сохраняется; иначе было бы угрозой безопасности. Это происходит с помощью ExecutionContext.

Я считаю, что культура течет с AspNetSynchronizationContext, но я не тестировал это на .NET 4.5 новой реализации.


Вы можете найти мою статью MSDN на SynchronizationContext. Это не официальная документация (я не работаю для Microsoft), но, по крайней мере, это что-то. Обратите внимание, что AspNetSynchronizationContext, на который ссылается в этой статье, теперь называется LegacyAspNetSynchronizationContext в .NET 4.5.

Еще один отличный ресурс - Stephen Toub ExecutionContext vs. SynchronizationContext.

Ответ 2

Хорошо, что захват ExecutionContext всегда гарантирован, захват и выполнение выполнения в том же SynchronizationContext зависит от Awaiter.

Самый распространенный awaiter (тип, возвращаемый методом GetAwaiter(), который внутренне вызывается, когда вы "ждёте" что-то), является TaskAwaiter, возвращаемым Task.GetAwaiter(). По умолчанию TaskAwaiter захватит текущий SynchronizationContext и запустит делегат продолжения на захваченном SynchronizationContext. Это означает, что вы сможете использовать HttpContext.Current в остальной части вашего метода, и вы не против, чтобы он выполнялся как продолжение. Таким образом, этот код будет работать так, как ожидалось (часть, где вы записываете "B", будет запускаться в том же контексте synchronizationcontext, что и первая строка):

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

Вы можете изменить это поведение с помощью метода Task.ConfigureAwait(false), который сообщает awaiter не помещать остальную часть метода обратно в исходный SynchronizationContext.

Конечно, если вы используете Task.Run или Task.Factory.StartNew в асинхронном методе, который вы вызываете, это ваша обязанность снова захватить SynchronizationContext.

Желаем удачи.