Может ли код после ожидания запускаться в другом потоке в ASP.NET?

Я прочитал здесь https://blog.stephencleary.com/2009/10/synchronizationcontext-properties.html, что контекст выполнения приложений ASP.NET не имеет определенного связанного потока. Означает ли это, что код после ожидания будет (может) выполняться в другом потоке с тем же контекстом? В таком случае, как это возможно, что тупик может быть вызван синхронным выполнением? Или приложение ASP.NET не подходит для такого тупика?

Заранее спасибо.


person Denys Alexieiev    schedule 03.02.2020    source источник
comment
ASP.NET предоставляет другой поток для каждого HTTP-запроса, и конкретный поток может фактически измениться из-за гибкость потоков. При этом конкретный HTTP-запрос будет обрабатываться только одним потоком за раз, поэтому вам не нужно lock обходить большинство переменных. Исключение составляют случаи, когда вы изо всех сил стараетесь заставить его работать иначе, например с помощью Task.Run.   -  person John Wu    schedule 04.02.2020
comment
Я думаю, что в этой статье имеется в виду, что классическая версия ASP.Net имеет контекст синхронизации, т.е. взаимоблокировка произойдет, когда продолжение пытается запустить блокирующий вызов, но нет определенного связанного потока, как в случае с Winforms, где есть основной / графический интерфейс поток, прикрепленный к синхронизации   -  person JohanP    schedule 04.02.2020
comment
@JohnWu, означает ли это, что если какой-то поток уже выполняется в HTTP-запросе и был заблокирован из-за тупиковой ситуации, то никакой другой поток не может продолжить выполнение?   -  person Denys Alexieiev    schedule 04.02.2020
comment
Не совсем ... Другие потоки могут запускать какой-то другой код, не связанный с исходным запросом (возможно, обрабатывая какой-то другой запрос), этот тупик (между заблокированным потоком, привязанным к контексту синхронизации исходного запроса, и асинхронным операция, пытающаяся продолжить в этом контексте) повлияет только на один поток, асинхронная операция, ожидающая выполнения продолжения, не потребует для себя дополнительного потока.   -  person Alexei Levenkov    schedule 04.02.2020


Ответы (1)


Для ASP.NET Classic (.NET Framework) существует специальный AspNetSynchronizationContext, продолжение будет отправлено обратно в исходный поток контекста.

ASP.NET Core нет. Если вы проверите SynchronizationContext.Current, вы обнаружите, что он установлен на null. Таким образом, продолжение может использовать любой поток, который он выберет, и не будет иметь классических взаимоблокировок в этом отношении.


Обновить

Некоторые отличные исправления от @StephenCleary в комментариях.

Незначительное исправление: в классическом ASP.NET SynchronizationContext представляет контекст запроса, а не конкретный поток.

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

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

person TheGeneral    schedule 03.02.2020
comment
Вы говорите, что для случая .NET Framework продолжение будет отправлено обратно в исходный контекст, однако, насколько я знаю, context! = Исходный поток. Джон Ву выше упомянул про ловкость нитей. Это случай с .NET Framework? Может ли пул потоков просто создать новый поток и назначить ему AspNetSynchronizationContext и продолжить выполнение, если исходный поток занят? - person Denys Alexieiev; 04.02.2020
comment
@DenysAlexieiev Если вы работаете во фреймворке с SynchronizationContext, не блокируйте async это так просто, вы рискуете попасть в тупик. Какую проблему ты пытаешься решить? - person TheGeneral; 04.02.2020
comment
Не уверен, что понимаю ваш последний ответ. Не могли бы вы добавить более подробную информацию? - person Denys Alexieiev; 04.02.2020
comment
Я действительно не решаю какую-то проблему. Просто пытаюсь понять, как это работает. - person Denys Alexieiev; 04.02.2020
comment
@DenysAlexieiev, формат вопросов и ответов не совсем подходящее место для подробных вопросов и ответов, возможно, если вы сначала взглянете на этот blog.stephencleary.com/2012/07/dont-block-on-async-code.html, если у вас есть дополнительные вопросы после этого вы можете опубликовать снова. - person TheGeneral; 04.02.2020
comment
Спасибо. Хорошая статья - person Denys Alexieiev; 04.02.2020
comment
Незначительное исправление: в классическом ASP.NET SynchronizationContext представляет контекст запроса, не конкретный поток. Метод может возобновиться в любом потоке пула потоков после await. Тупиковая ситуация возникает из-за того, что в контексте этого запроса есть блокировка, чтобы гарантировать, что только один поток одновременно может находиться в контексте запроса. Итак, когда метод async готов к возобновлению, берется поток пула потоков, который входит в контекст запроса и пытается взять эту блокировку. Если другой поток заблокирован для этой задачи в контексте, блокировка уже взята, и произойдет взаимоблокировка. - person Stephen Cleary; 04.02.2020
comment
@StephenCleary, спасибо за эти исправления, я не был доволен тем, как я это сформулировал. Я обновил его вашими комментариями и приписал их, а также узнал еще кое-что в процессе. ваше здоровье! - person TheGeneral; 04.02.2020