Для быстрого обучения ..
Разобраться в потоке выполнения метода (с диаграммой): 3 минуты
Вопрос самоанализ (ради обучения): 1 мин
Быстро пройти через синтаксис сахара: 5 минут
Поделитесь смущением разработчика: 5 минут
Проблема: Быстрое изменение реальной реализации нормального кода на асинхронный код: 2 минуты
Куда дальше?
Разобраться в потоке выполнения метода (с диаграммой): 3 минуты
На этом изображении, просто сфокусируйтесь на # 6 (больше ничего)
На шаге № 6: выполнение здесь остановлено, так как оно закончилось без работы. Для продолжения нужен результат из getStringTask (вид функции). Следовательно, он использует await
оператор, чтобы приостановить свой прогресс и вернуть управление (yield) вызывающей стороне (в этом методе мы находимся). Фактический вызов 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;
}
Task-ified метод для вызова вышеуказанного метода
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;
}
Мы упомянули await или async? Нет. Вызовите вышеуказанный метод, и вы получите задачу, которую можете отслеживать. Вы уже знаете, что возвращает задание .. целое число.
Вызов задачи немного сложен, и именно тогда ключевые слова начинают появляться. Давайте назовем MethodTask ()
internal static async Task<int> MethodAsync(int arg0, int arg1)
{
int result = await HelperMethods.MethodTask(arg0, arg1);
return result;
}
Тот же код выше добавлен как изображение ниже:
- Мы «ожидаем» задачи, которая будет завершена. Следовательно
await
- Так как мы используем await, мы должны использовать
async
(обязательный синтаксис)
- MethodAsync с
Async
префиксом (стандарт кодирования)
await
это легко понять, но остальные два ( async
, Async
) могут не быть :). Ну, это должно сделать намного больше смысла компилятор though.Further читает для последующего использования здесь
Итак, есть 2 части.
- Создать «Задача»
- Создать синтаксический сахар для вызова задачи (
await+async
)
Помните, у нас был внешний вызывающий объект для AccessTheWebAsync (), и этот вызывающий также не избавлен ... т.е. ему await+async
тоже нужно то же самое. И цепь продолжается. Но всегда будет Task
один конец.
Все хорошо, но один разработчик был удивлен, увидев, что # 1 (Задача) отсутствует ...
Поделитесь смущением разработчика: 5 минут
Разработчик допустил ошибку, не реализовав, Task
но это все еще работает! Постарайтесь понять вопрос и просто принятый ответ, приведенный здесь . Надеюсь, что вы прочитали и полностью поняли. Суть в том, что мы можем не видеть / реализовывать «Задачу», но она реализована где-то в родительском классе. Аналогично, в нашем примере вызов уже созданного MethodAsync()
способа проще, чем реализация этого метода с помощью Task
( MethodTask()
). Большинству разработчиков трудно передумать Tasks
при преобразовании кода в асинхронный.
Совет: попробуйте найти существующую реализацию Async (например, MethodAsync
или ToListAsync
), чтобы передать сложность на аутсорсинг. Таким образом, нам нужно иметь дело только с Async и await (что легко и очень похоже на обычный код)
Проблема: быстро изменить реальную реализацию нормального кода на асинхронную работу: 2 минуты
Строка кода, показанная ниже в Data Layer, начала ломаться (много мест). Потому что мы обновили часть нашего кода с .Net Framework 4.2. * До ядра .Net. Мы должны были исправить это за 1 час по всему приложению!
var myContract = query.Where(c => c.ContractID == _contractID).First();
очень просто!
- Мы установили пакет nuget EntityFramework, потому что он имеет QueryableExtensions. Или, другими словами, это делает реализацию (задачу) Async, чтобы мы могли выжить с простыми
Async
иawait
в коде.
- namespace = 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 Core мы могли бы посмотреть замечательное короткое видео о преобразовании синхронных вызовов в асинхронные , возможно, именно в этом направлении можно было бы двигаться после прочтения этого.