Гаразд, ось моя думка про це.
Існує щось, що називається корутинами, про що відомо десятиліттями. ("Класс і Хоппер" -клас "десятиліттями") Вони є узагальненням підпрограм , таких як вони не тільки отримують і звільняють контроль при операції запуску і повернення функції, але і роблять це в конкретних точках ( точках припинення ). Підпрограма - це підпрограма без точок припинення.
Їх ГРУТИ ЛЕГКО реалізувати за допомогою макросів C, як показано у наступній статті про "прототрафах". ( http://dunkels.com/adam/dunkels06protothreads.pdf ) Прочитайте. Я почекаю...
Суть цього полягає в тому, що макроси створюють велику switchта caseмітку в кожній точці підвіски. У кожній точці призупинення функція зберігає значення негайно наступногоcase мітки, так що вона знає, де відновити виконання наступного разу, коли вона буде викликана. І це повертає контроль абоненту.
Це робиться без зміни видимого потоку управління кодом, описаного в "прототраді".
Уявіть собі, що у вас є великий цикл, що викликає по черзі всі ці "прототони", і ви одночасно виконуєте "прототради" на одному потоці.
Цей підхід має два недоліки:
- Ви не можете зберігати стан у локальних змінних між відновленнями.
- Ви не можете призупинити "прототрейд" з довільної глибини виклику. (усі точки підвіски повинні бути на рівні 0)
Для обох є вирішення:
- Усі локальні змінні повинні бути підтягнуті до контексту прототрадування (контекст, який вже потрібен тому, що прототрафа повинна зберігати свою наступну точку відновлення)
- Якщо ви відчуваєте, що вам дійсно потрібно зателефонувати ще з прототрафа, "нерестуйте" прототипу дитини та призупиніть до завершення роботи дитини.
І якби у вас була підтримка компілятора, щоб виконати роботу з перезапису, яку виконують макроси та обхідний шлях, ви можете просто написати свій код протокредиту так, як ви плануєте, і вставити пункти призупинення з ключовим словом.
А це що asyncіawait : створення (без стоп) розслідувань.
Співпраці в C # переробляються як об'єкти (загального або негенеричного) класу Task .
Я вважаю ці ключові слова дуже оманливими. Моє розумове читання:
async як "підвісний"
await як "призупинити до завершення"
Task як "майбутнє ..."
Тепер. Чи дійсно нам потрібно позначити функцію async? Крім того, що він повинен запускати механізми перезапису коду, щоб перетворити функцію на супровід, він вирішує деякі неясності. Розглянемо цей код.
public Task<object> AmIACoroutine() {
var tcs = new TaskCompletionSource<object>();
return tcs.Task;
}
Якщо припустити, що asyncце не є обов'язковим, це поправка чи нормальна функція? Чи повинен перекладач переписати його як супровід чи ні? І те й інше може бути можливим з різною можливою семантикою.