В C # 7.3 у вас могут быть асинхронные точки входа, я предлагаю использовать это.
Некоторые заметки:
- Не используйте async void, у него есть тонкости в том, как он работает с ошибками, если вы видите, что пишете самостоятельно async void, подумайте о том, что вы делаете. Если это не для обработчика событий, вы, вероятно, делаете что-то не так
- Если вы хотите дождаться завершения ряда задач, используйте
Task.WhenAll
Модифицированный пример
static async Task Main(string[] args)
{
Console.WriteLine("Start Task");
var task = Program.step1();
for (int i = 0; i < 6; i++)
{
await Task.Delay(100);
Console.WriteLine("Sleep-Loop");
}
Console.WriteLine("waiting for the task to finish");
await task;
Console.WriteLine("finished");
Console.ReadKey();
}
private static async Task step1()
{
await Task.Delay(1000);
Console.WriteLine("Step1");
await Program.step2();
}
private static async Task step2()
{
await Task.Delay(1000);
Console.WriteLine("Step2");
}
Важно отметить, что задачи не являются потоками, а async
не параллельны, однако они могут быть.
В 9 случаях из 10, если вы используете шаблон асинхронного ожидания, работа, связанная с вводом-выводом, должна использовать порты завершения ввода-вывода операционной системы, чтобы вы могли освободить потоки. Это функция масштабируемости и отзывчивости пользовательского интерфейса.
Если вы не выполняете какую-либо работу по вводу-выводу, тогда на самом деле очень мало необходимости в шаблоне async
await
, и поэтому такая работа процессора, вероятно, должна быть просто заключена в Task.Run
в точке звонить. Не упаковано в методе async
.
В этот момент также полезно отметить, что использование задач - это не шаблон асинхронности и ожидания. Хотя у них обоих есть общие задачи, они не одно и то же.
И последнее, если вам нужно использовать асинхронный код с огнем и забыть, очень тщательно подумайте, как вы будете обрабатывать любые ошибки.
Вот несколько рекомендаций.
- Если вы хотите выполнить IO, используйте шаблон асинхронного ожидания.
- Если вы хотите выполнить работу процессора, используйте Task.Run.
- Никогда не используйте async void, кроме как для обработчика событий.
- Никогда не переносите работу процессора асинхронным методом, пусть вызывающая сторона использует
Task.Run
- Если вам нужно дождаться задания,
await
, никогда не звоните Result
, или Wait
, или используйте Task.WhenAll