AsyncLocal значение равно Null после установки из приложения BeginRequest()
В следующем примере я устанавливаю значение переменной AsyncLocal<string> в моем подклассе HttpApplication (т. е. Global.asax) изнутри Application_BeginRequest():
public class Global : System.Web.HttpApplication
{
public static AsyncLocal<string> AsyncLocalState = new AsyncLocal<string>();
protected void Application_BeginRequest(object sender, EventArgs e)
{
AsyncLocalState.Value = HttpContext.Current.Request.Path;
}
protected void Application_AuthenticateRequest(object sender, EventArgs e)
{
var path = AsyncLocalState.Value;
}
protected void Application_EndRequest(object sender, EventArgs e)
{
var path = AsyncLocalState.Value;
}
}
Позже я попытаюсь получить доступ к значению этой переменной AsyncLocal из обработчика, такого как метод действия MVC, или даже просто IHttpHandler.
Если я отправляю достаточно большой запрос (например, сообщение с более чем 15 КБ данных - чем больше запрос, тем легче его наблюдать), есть очень хороший шанс, что значение AsyncLocalState имеет значение NULL при обращении из обработчика , даже если он был установлен на BeginRequest.
Это воспроизводимо из совершенно нового ASP.NET проект без каких-либо других загруженных библиотек/модулей/обработчиков.
Это ошибка? Или, может быть, я делаю что-то не так? Или есть ASP.NET просто слишком нестабильна для этого?
Дополнение Примечание: точно такое же поведение наблюдается, если я вместо этого использую CallContext.LogicalGetData/CallContext.LogicalSetData.
Платформа: ASP.NET, .NET 4.6.2, на Windows 7
Обновление: После попытки покопаться, я нашел много ссылок на, но ничего авторитетно говорящего о том, что ExecutionContext не течет ли между ASP.NET события конвейера (кроме тех случаев, когда это происходит?). И как AsyncLocal, так и логический контекст вызова основаны на ExecutionContext.
1 ответ:
Наиболее близким к авторитетному ответу являетсяэтот комментарий отДэвида Фаула на GitHub.
ExecutionContextне течет между ASP.NET события конвейера, если эти события не выполняются синхронно. Поэтому не используйтеAsyncLocalили логическоеCallContextдля сохранения состояния; используйтеHttpContext.Items.Обновление: .NET 4.7.1 добавляет новый метод обратного вызова,
HttpApplication.OnExecuteRequestStep, который в соответствии с документацией " обеспечивает расширяемость ASP.NET конвейер, чтобы сделать его легким для разработчиков, чтобы реализуйте функции в сценариях окружающего контекста и создавайте библиотеки, которые заботятся о ASP.NET поток выполнения (например, трассировка, профилирование, диагностика и транзакции). "Это именно то, что кому-то понадобится для восстановления состояния
AsyncLocalили логическогоCallContextмежду ASP.NET события конвейера.
Comments