Итак, у вас есть не асинхронный c метод, и в этом не асинхронном c методе вы хотите вызывать асинхронные c методы.
Обычно метод асинхронный c, потому что где-то глубоко внутри вашей нити приходится ждать другого длинного процесса до конца sh. Подумайте о файле, который нужно записать, о запросе к базе данных или о некоторой информации, извлекаемой из inte rnet. Обычно это функции, в которых асин c методы находятся рядом с не-асин c методами.
Вместо того, чтобы бездействовать, ожидая, пока другой процесс завершит sh свою задачу, вызывающую метод получает контроль над другими вещами, пока не увидит ожидание. Вызывающему предоставляется управление до тех пор, пока он не увидит ожидающего и т. Д. c.
Так что, если вы хотите делать другие вещи, пока другой процесс выполняет свою задачу: просто не ждите. Проблема, конечно, заключается в следующем: вы хотите узнать результат другой задачи, прежде чем ваша функция завершится. Если вы этого не сделаете, если вам будет сложно определить условия публикации вашего метода.
void MyMethod()
{
Task<int> taskA = MethodAasync(...);
// you didn't await, you are free to do something else, like calling another async method
Task<double> taskB = MethodBasync(...);
DoSomethingUseful();
// if here, you need the result of taskA. Wait until it is ready
// this blocks your thread!
taskA.Wait();
int resultA = taskA.Result();
ProcessResult(resultA);
// if desired, you can wait for a collection of tasks:
Task[] tasksToWaitFor = new Task[] {taskA, taskB};
Task.WaitAll(tasksToWaitFor);
int resultA = taskA.Result();
double resultB = taskB.Result();
ProcessResults(resultA, resultB);
}
Даже если вас не интересует результат выполнения заданий, будет целесообразно дождаться их завершения sh. Это позволяет реагировать на исключения.
Кстати, вы видели, что я не звонил Task.Run
! Что происходит, так это то, что мой поток входит в MethodAasyn c до тех пор, пока не увидит ожидание. Затем процедура возвращается к управлению, поэтому она входит в MethodBasyn c, пока не увидит ожидание. Ваша процедура возвращает управление DoSomethingUseful.
Как только другой процесс (запрос к базе данных, файл записи и т. Д. c) завершен, один из потоков пула потоков продолжает обрабатывать операторы после ожидания До тех пор, пока он не встретит новое ожидание, или пока больше нечего обрабатывать.
Task.Wait
и Task.WaitAll
- это методы, которые останавливают эту асинхронность: поток действительно блокируется до тех пор, пока все асинхронные c методы не будут полностью завершены.
Редко есть причина использовать Task.Run, если вы хотите вызвать асинхронный метод c: просто вызовите его, не ждите его, чтобы вы могли делать другие полезные вещи. Обязательно дождитесь, пока задача завершится sh, как только вам понадобится результат, или самое позднее, когда вы вернете метод.
Другой способ - вернуть задачи, не ожидая их завершения. sh, чтобы дать звонящему возможность сделать что-то полезное, если задачи не выполнены. Конечно, это может быть сделано только в том случае, если вашей процедуре не нужен результат задачи. Он также обязывает вашего абонента ждать завершения или передавать задачи своему вызывающему.
Единственная причина для Task.Run, которую я вижу, в том, что вы хотите запустить длительную процедуру в своем собственном процессе, что вы не хотите ждать прямо сейчас. Подумайте о длительных расчетах. Не используйте Task.Run, если задействован другой процесс. В этом случае другой процесс должен иметь функцию asyn c, или вы должны создать метод расширения asyn c, который выполняет задачу. Запуск.
int DoSomeLengthyCalculations(...) {...};
async Task<MyResult> CalculateIt(...)
{
Task<int> taskLengthyCalculations = Task.Run( () => DoSomeLengthyCalculations(...);
// if desired DoSomethingUsefull; after that wait for the task to end
// and process the result:
Task.Wait(taskLengthyCalculations);
int resultLengthyCalculations = taskLengthyCalucalations.Result();
MyResult result = ProcessResult(resultLengthyCalculations);
return result;
}
Приятно, что вы скрыто ли вы делаете длительные вычисления, или что кто-то другой делает это. Например, если вы используете методы модульного тестирования, которые asyn c обращаются к базе данных, вы можете смоделировать это при обращении к словарю. }