Сон действительно блокирует выполнение? - PullRequest
0 голосов
/ 10 марта 2019

Практически каждое введение в асинхронное программирование для C # предостерегает от использования инструкции Sleep, поскольку она блокирует весь поток.

Но я обнаружил, что во время сна задачи из очереди выбираются и выполняются.См .:

    using System;
    using System.Threading.Tasks;

    namespace TestApp {
        class Program
        {
            static void Main(string[] args)
            {
                Console.WriteLine("Main");
                Program.step1();

                for (int i = 0; i < 6; i++) {
                    System.Threading.Thread.Sleep(200);
                    Console.WriteLine("Sleep-Loop");
                }
            }

            private static async void step1() {
                await Task.Delay(400);
                Console.WriteLine("Step1");
                Program.step2();
            }

            private static async void step2() {
                await Task.Delay(400);
                Console.WriteLine("Step2");
            }
        }
    }

Вывод:

    Main
    Sleep-Loop
    Sleep-Loop
    Step1
    Sleep-Loop
    Sleep-Loop
    Step2
    Sleep-Loop
    Sleep-Loop

Мои вопросы:

  1. Действительно ли Sleep позволяет выполнять поставленные в очередь задачи или что-то еще происходит?
  2. Если да, то происходит ли это и во всех остальных случаях безделья?Например, во время опроса?
  3. В приведенном выше примере, если мы закомментируем цикл, приложение завершит работу, прежде чем могут быть выполнены какие-либо задачи.Есть ли другой способ предотвратить это?

1 Ответ

2 голосов
/ 10 марта 2019

В C # 7.3 у вас могут быть асинхронные точки входа, я предлагаю использовать это.

Некоторые заметки:

  1. Не используйте async void, у него есть тонкости в том, как он работает с ошибками, если вы видите, что пишете самостоятельно async void, подумайте о том, что вы делаете. Если это не для обработчика событий, вы, вероятно, делаете что-то не так
  2. Если вы хотите дождаться завершения ряда задач, используйте 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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...