Після деякого часу, маючи справу з асинхронною / очікуваною схемою C #, я раптом зрозумів, що я не знаю, як пояснити, що відбувається в наступному коді:
async void MyThread()
{
while (!_quit)
{
await GetWorkAsync();
}
}
GetWorkAsync()
передбачається повернути очікуване, Task
що може або не спричинить перемикання потоку при виконанні продовження.
Я б не плутався, якби очікування не було в циклі. Я, природно, очікував, що решта методу (тобто продовження) потенційно може виконуватись на іншій нитці, що добре.
Однак усередині циклу поняття "решта методу" для мене стає трохи туманним.
Що станеться з "рештою циклу", якщо потік увімкнено продовження проти, якщо він не перемикається? На якій нитці виконується наступна ітерація циклу?
Мої спостереження показують (не остаточно підтверджено), що кожна ітерація починається на одній нитці (початковій), а продовження виконується на іншій. Це може бути насправді? Якщо так, то чи є це ступінь несподіваного паралелізму, який потрібно враховувати для безпеки потоку методу GetWorkAsync?
ОНОВЛЕННЯ: Моє запитання не є дублікатом, як пропонують деякі. while (!_quit) { ... }
Кодовий просто спрощення мого фактичного коду. Насправді мій потік - це довговічний цикл, який обробляє свою вхідну чергу робочих елементів регулярно (кожні 5 секунд за замовчуванням). Фактична перевірка стану виходу - це не проста перевірка поля, як запропоновано зразковим кодом, а скоріше перевірка обробки події.