Не ожидаемый поток просто прекращает выполнение после возврата api, это известная ошибка или кто-нибудь может объяснить, что происходит? - PullRequest
1 голос
/ 15 апреля 2019

Если у меня есть контроллер api, и я хочу, чтобы он возвращался пользователю как можно быстрее, в то же время, раскручивая поток для обработки более продолжительного процесса, я подумал, что просто не могу ожидать вызова асинхронного метода, подобного этому.

DoSomeNonAwaitedAsyncThing(data);
var result = await DoSomeNormalAsyncThing(data);
return result;

Но код DoSomeNonAwaitedAsyncThing перестанет выполняться при возврате контроллера api (без исключений или чего-либо еще, что он просто перестает работать).

Если я изменю сигнатуру DoSomeNonAwaitedAsyncThing с асинхронной задачи на async void , тогда поток будет выполняться до завершения, но он также будет блокировать возврат вызова API до тех пор, пока не будет получена не ожидаемая задача.complete.

также, если я изменю способ вызова метода на этот (ниже), то метод будет выполняться до завершения, а не останавливаться на полпути через метод.

Task.Run(async () => { DoSomeNonAwaitedAsyncThing(data); }); 

Iсоздал репо с проектом, чтобы продемонстрировать проблему.https://github.com/JamesWebDev/AsyncThreadIssueExample

Также стоит отметить, что я добавил это в веб-конфигурацию, чтобы он позволял возвращать вызов API, пока потоки еще работают.

<add key="aspnet:AllowAsyncDuringSyncStages" value="true"/>

1 Ответ

1 голос
/ 17 апреля 2019

Код DoSomeNonAwaitedAsyncThing перестанет выполняться, когда контроллер API вернет

Скорее всего, проблема заключается в том, что DoSomeNonAwaitedAsyncThing пытается повторно войти в контекст запроса ASP.NET Classic.По умолчанию await захватит текущий контекст и возобновит работу в этом контексте ;в ASP.NET Classic этот «контекст» является контекстом запроса ASP.NET Classic.Однако, поскольку запрос, на который ссылается этот контекст запроса, уже уже выполнен , это может вызвать ... осложнения.

Причина, по которой он работает с Task.Run, заключается в том, что текущий контекст для DoSomeNonAwaitedAsyncThing больше не является контекстом запроса ASP.NET Classic;теперь это контекст пула потоков.И пул потоков все еще там, когда await внутри DoSomeNonAwaitedAsyncThing готов к продолжению.

В качестве оптимальной практики вам следует избегать запретов на запуск и запуск в ASP.NET (это верно как для Classic, так и для Core).Правильным решением является запись вашего контроллера в надежную очередь (например, очередь Azure) и независимый фоновый процесс, выполняющий эту операцию (например, функция Azure).Существуют альтернативы независимому фоновому процессу - HostingEnvironment.QueueBackgroundWorkItem и IRegisteredObject для Classic, и IHostedService и IHostApplicationLifetime для Core - но суть в том, что вам на минимум нужна надежная очередь междуваш контроллер и фоновый процесс.В противном случае вы можете потерять работу во время выключения / перезапуска.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...