Для швидкого навчання ..
Зрозумійте потік виконання методу (з діаграмою): 3 хв
Самоаналіз питань (заради навчання): 1 хв
Швидко пройти через синтаксичний цукор: 5 хв
Поділіться плутаниною розробника: 5 хв
Проблема: Швидко змінити реалізацію звичайного коду в реальному світі на код Async: 2 хвилини
Куди далі?
Зрозумійте потік виконання методу (з діаграмою): 3 хв
У цьому зображенні просто зосередьтеся на №6 (нічого більше)
На кроці №6: Виконання тут зупинилося, оскільки закінчилося роботу. Щоб продовжити, йому потрібен результат від getStringTask (вид функції). Тому він використовує await
оператор, щоб призупинити свій прогрес і повернути абоненту управління (вихід) (цього методу ми використовуємо). Фактичний виклик до getStringTask був здійснений раніше у # 2. У №2 було обіцяно повернути рядковий результат. Але коли це поверне результат? Чи повинні ми (# 1: AccessTheWebAsync) зробити другий дзвінок ще раз? Хто отримує результат, №2 (заява на виклик) або №6 (очікує заяву)
Зараз зовнішній абонент AccessTheWebAsync () також чекає. Тож абонент, який чекає AccessTheWebAsync, і AccessTheWebAsync на даний момент чекає GetStringAsync. Цікава річ, що AccessTheWebAsync зробив певну роботу перед очікуванням (# 4), можливо, щоб заощадити час від очікування. Така ж свобода багатозадачності також доступна для зовнішнього абонента (і всіх абонентів у ланцюжку), і це найбільший плюс цієї «асинхронної» речі! Ви відчуваєте, що це синхронно ... або нормально, але це не так.
Пам'ятайте, що метод уже повернуто (№2), він не може повернутися знову (не вдруге). Отже, як дізнається абонент? Це все про завдання! Завдання було прийнято. Завдання чекали (не метод, не значення). Значення буде встановлено у Завдання. Статус завдання буде встановлено для завершення. Абонент просто стежить за завданням (№6). Отже 6 # - це відповідь на те, де / хто отримує результат. Далі читайте для подальшого тут .
Самоаналіз питань заради навчання: 1 хв
Давайте трохи відрегулюємо питання:
Як і коли використовувати та ? async
await
Tasks
Оскільки навчання Task
автоматично охоплює інші два (і відповідає на ваше запитання)
Швидко пройти через синтаксичний цукор: 5 хв
До конверсії (оригінальний метод)
internal static int Method(int arg0, int arg1)
{
int result = arg0 + arg1;
IO(); // Do some long running IO.
return result;
}
метод, визначений завданням, для виклику вищевказаного методу
internal static Task<int> MethodTask(int arg0, int arg1)
{
Task<int> task = new Task<int>(() => Method(arg0, arg1));
task.Start(); // Hot task (started task) should always be returned.
return task;
}
Ми згадали про очікування чи асинхронізацію? Ні. Зателефонуйте до описаного вище способу, і ви отримаєте завдання, яке ви зможете контролювати. Ви вже знаєте, що повертає завдання .. ціле число.
Виклик завдання - трохи складний, і саме тоді ключові слова починають з’являтися. Зателефонуємо MethodTask ()
internal static async Task<int> MethodAsync(int arg0, int arg1)
{
int result = await HelperMethods.MethodTask(arg0, arg1);
return result;
}
Той самий код, що додається вище, як і зображення нижче:
- Ми чекаємо, що завдання буде завершено. Отже
await
- Оскільки ми використовуємо функцію очікування, ми повинні використовувати
async
(обов'язковий синтаксис)
- MethodAsync з
Async
префіксом (стандарт кодування)
await
легко зрозуміти, але решта двох ( async
, Async
) може бути не :). Хоча, це має мати набагато більше сенсу для компілятора. Далі читайте тут для подальшого
Отже, є 2 частини.
- Створіть "Завдання"
- Створіть синтаксичний цукор для виклику завдання (
await+async
)
Пам’ятайте, у нас був зовнішній абонент до AccessTheWebAsync (), і той абонент також не пощадив ... тобто він теж потрібен await+async
. І ланцюг продовжується. Але завжди знайдеться Task
в одному кінці.
Все гаразд, але один розробник був здивований, побачивши, що №1 (Завдання) відсутній ...
Поділіться плутаниною розробника: 5 хв
Розробник помилився тим, що не реалізує, Task
але це все ще працює! Постарайтеся зрозуміти питання і просто прийняту відповідь, надану тут . Сподіваюся, ви прочитали і повністю зрозуміли. Підсумок полягає в тому, що ми можемо не бачити / реалізовувати "Завдання", але він реалізований десь у батьківському класі. Так само в нашому прикладі викликати вже побудований MethodAsync()
спосіб набагато простіше, ніж реалізувати цей метод за допомогою Task
( MethodTask()
) себе. Більшість розробників важко обернутися Tasks
, перетворюючи код на асинхронний.
Порада. Спробуйте знайти існуючу програму Async (як-от MethodAsync
або ToListAsync
), щоб передавати труднощі. Тому нам потрібно мати справу лише з Async і чекати (що легко і досить схоже на звичайний код)
Проблема: Швидко змінити реалізацію звичайного коду в режимі Async: 2 хвилини
Рядок коду, показаний нижче в шарі даних, почав розбиватися (багато місць). Оскільки ми оновили деякий наш код із .Net Framework 4.2. * До .Net core. Нам довелося виправити це за 1 годину впродовж усієї програми!
var myContract = query.Where(c => c.ContractID == _contractID).First();
Простенька!
- Ми встановили Nuget пакет EntityFramework, оскільки він має QueryableExtensions. Або іншими словами, це реалізація (завдання) Async, тому ми могли вижити просто
Async
і await
в коді.
- простір імен = Microsoft.EntityFrameworkCore
Рядок коду виклику змінився так
var myContract = await query.Where(c => c.ContractID == _contractID).FirstAsync();
Підпис методу змінено з
Contract GetContract(int contractnumber)
до
async Task<Contract> GetContractAsync(int contractnumber)
Метод виклику також постраждав: GetContractAsync(123456);
був викликаний якGetContractAsync(123456).Result;
Ми змінили його скрізь за 30 хвилин!
Але архітектор сказав нам не використовувати бібліотеку EntityFramework саме для цього! ой! драма! Тоді ми зробили власну реалізацію завдань (юк). Який ти вмієш. Ще легко! ..шти юк ..
Куди далі?
Є чудове швидке відео, яке ми могли б подивитися про перетворення синхронізованих дзвінків в асинхронні в ядрі ASP.Net , можливо, це, мабуть, напрямок, який слід піти після прочитання цього.