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.

562   1  

1 ответ:

Наиболее близким к авторитетному ответу являетсяэтот комментарий отДэвида Фаула на GitHub.

ExecutionContext не течет между ASP.NET события конвейера, если эти события не выполняются синхронно. Поэтому не используйте AsyncLocal или логическое CallContext для сохранения состояния; используйте HttpContext.Items.

Обновление: .NET 4.7.1 добавляет новый метод обратного вызова, HttpApplication.OnExecuteRequestStep, который в соответствии с документацией " обеспечивает расширяемость ASP.NET конвейер, чтобы сделать его легким для разработчиков, чтобы реализуйте функции в сценариях окружающего контекста и создавайте библиотеки, которые заботятся о ASP.NET поток выполнения (например, трассировка, профилирование, диагностика и транзакции). "

Это именно то, что кому-то понадобится для восстановления состояния AsyncLocal или логического CallContext между ASP.NET события конвейера.

Comments

    Ничего не найдено.