0

Как мне написать свой асинхронный метод, который, например, выводит на экран последовательность чисел? (Предполагается, что Console.WriteLine будет блокировать этот поток, он же все равно работает быстро). То есть я хочу, например, создать 2 таски, которые будут по очереди выводить по числу в консоль. При помощи генераторов я представляю, как решить эту задачу, а как при помощи асинхронного кода?

Scrzii
  • 186
  • 8
  • Для асинхронной работы нужна асинхронная задача. Вывод в консоль синхронный и выкидывать его в поток - дороже по времени, чем отправить вывод напрямую. То есть, мне не до конца понятно, что вам нужно. Теоретически предположу, что вам стоит призучать шаблон проектирования Producer/Consumer и реализующие его классы типа System.Collections.Concurrent.BlockingCollection и System.Threading.Channels.Channel. Ну и всякие трюки с многопоточкой типа этого. – aepot Nov 26 '21 at 18:28
  • Мне это нужно для того, чтобы поучиться работать с асинхронными задачами, не так важно, насколько эффективно или неэффективно мое решение для этой конкретной задачи, важно понять, как мне писать асинхронный код – Scrzii Nov 26 '21 at 19:22
  • А что его учиться писать, писать его просто, ради этого async/await и придумали. Для того чтобы пошло дело, надо понять - зачем придумали. Вот тогда станет ясно, какие задачи с помощью этого подхода надо решать. Заворачивать в поток синхронную операцию много ума не требуется. Асинхронное программирование. Вот еще пример. – aepot Nov 26 '21 at 23:13
  • Асинхронный вывод с помощью реактивного подхода(System.Reactive): https://dotnetfiddle.net/fFuRGp – Lapish Nov 27 '21 at 12:36

1 Answers1

0

Я нашел решение, которое мне было нужно. Инструкция await внутри асинхронного метода заставляет выходить обратно в планировщик, пока действие не закончено. Мне был интересен метод, который заставляет выходить в планировщик безусловно, им оказался Task.Yield(). В итоге решение этой задачи выглядит примерно так:

static async Task Out(int n, int x)
{
    for (int i = 0; i < n; i++)
    {
        Console.WriteLine(x);
        await Task.Yield();
    }
}

static async Task MyOut() { var t1 = Out(10, 1); var t2 = Out(10, 2); var tasks = new List<Task> { t1, t2 }; while (tasks.Count > 0) { var ready = await Task.WhenAny(tasks); tasks.Remove(ready); } }

static void Main(string[] args) { Console.WriteLine("Started"); var task = MyOut(); task.Wait(); Console.WriteLine("Finished"); }

В результате вывод будет примерно такой:
Started
1
2
1
2
1
2
2
2
2
2
2
2
2
1
1
1
1
1
1
1
Finished
Вызов методов происходит не прямо друг за другом, я предполагаю, что есть какое-то минимальное ограничение в тиках на выполнение кусочка асинхронной задачи, но могу ошибаться. Поправьте меня, если я неправ.

Scrzii
  • 186
  • 8