Как asyn c void методы сообщают о прогрессе в ASP. NET Базовых приложениях - PullRequest
4 голосов
/ 15 апреля 2020

In. NET Framework, методы async void уведомляли свой контекст синхронизации при запуске или завершении, и любое исключение, выброшенное из метода async void, было напрямую вызвано в контекст синхронизации . В ASP. NET Core этот контекст синхронизации был удален .

Так, где метод async void сообщает, что он запущен, завершен, и если какие-либо исключения произошли в ASP. NET Базовое приложение, поскольку контекст синхронизации больше не существует?

Ответы [ 2 ]

8 голосов
/ 26 апреля 2020

TLDR: Нет синхронизации c контекст, означающий, что контекст не проинформирован о начале и завершении операции. Исключения генерируются в потоке пула потоков.

Метод async void преобразуется компилятором. Возьмите это в качестве примера

public async void Test() 
{
}

Результирующий сгенерированный код выглядит примерно так

public void Test()
{
    <Test>d__0 stateMachine = new <Test>d__0();
    stateMachine.<>4__this = this;
    stateMachine.<>t__builder = AsyncVoidMethodBuilder.Create();
    stateMachine.<>1__state = -1;
    AsyncVoidMethodBuilder <>t__builder = stateMachine.<>t__builder;
    <>t__builder.Start(ref stateMachine);
}

Важной частью здесь является AsyncVoidMethodBuilder struct. Глядя на функцию Create(), вы можете увидеть, что она пытается найти текущий SynchronizationContext, если он есть, затем вызвать virtual OperationStarted(). Поскольку для ядра. net нет контекста syn c, это будет пропущено.

Следующая интересная часть этого компоновщика - AwaitUnsafeOnCompleted(). Эта функция вызывается, когда внутри вашего метода у вас есть await. Если там возникает исключение, происходит ThrowAsync(), что вызывает исключение в потоке потоков, поскольку отсутствует контекст syn c.

6 голосов
/ 23 апреля 2020

async void методы уведомляли свой контекст синхронизации, когда они запускались или заканчивались, и любое исключение, выбрасываемое из асинхронного c пустого метода, было напрямую вызвано контекстом синхронизации

Эти методы никогда не уведомлять контекст синхронизации. Вместо этого их можно запланировать на выполнение в контексте синхронизации, если таковой имеется.

Если контекст синхронизации не задан при возобновлении продолжения задачи, TaskScheduler используется и всегда есть TaskScheduler.

В ASP. NET Ядро, этот контекст синхронизации был удален

Да, этот контекст синхронизации относится к AspNetSynchronizationContext в ASP. NET (не Core), который отвечает за ввод контекста HTTP-запроса, так что данные, указывающие c на запрос, могут быть используется в асин c методах. например, HttpContext.Current установлено.

Как эти данные обрабатывались в ASP. NET Ядро было изменено, поэтому больше нет необходимости сохранять такой проблемный c контекст синхронизации.

Удаление этого контекста синхронизации не означает, что контекст синхронизации удален из. NET Core.

...