Параллельный многострочный вывод в консоль

#c# #concurrency #console #command-line-interface #multiline

#c# #параллелизм #консоль #интерфейс командной строки #многострочный

Вопрос:

Я разработал интерфейс командной строки, который загружает различные типы данных в базу данных и выводит статус каждой загрузки на консоль.

 class Program
{
    static ConsoleColor DefaultColor;
    static void Main(string[] args)
    {
        DefaultColor = Console.ForegroundColor;

        string[] names = { "order", "fidelity", "button", "user" };
        foreach(var n in names)
        {
            Refresh(n);
        }
        Console.ReadKey();
    }


    static void Refresh(string name)
    {
        Console.Write($"Refresh {name,10} ... ");

        int random = new Random().Next();
        int delay = random % 1000   1000;
        Task.Delay(delay).Wait();
        if (random % 2 == 0)
        {
            Console.ForegroundColor = ConsoleColor.Green;
            Console.WriteLine($"OK ({delay,6} ms)");
            Console.ForegroundColor = DefaultColor;
        }
        else
        {
            Console.ForegroundColor = ConsoleColor.Red;
            Console.WriteLine("KO");
            Console.ForegroundColor = DefaultColor;
        }
    }
}
  

Каждый

 class Program
{
    static ConsoleColor DefaultColor;
    static void Main(string[] args) => MainTask(args).GetAwaiter().GetResult();

    static async Task MainTask(string[] args)
    {
        DefaultColor = Console.ForegroundColor;

        string[] names = { "order", "fidelity", "button", "user" };
        await LoopAsync(names);

        Console.ReadKey();
    }

    public static async Task LoopAsync(IEnumerable<string> thingsToLoop)
    {
        List<Task> listOfTasks = new List<Task>();

        foreach (var thing in thingsToLoop)
        {
            listOfTasks.Add(Refresh(thing));
        }

        await Task.WhenAll(listOfTasks);
    }

    static async Task Refresh(string name)
    {
        Console.Write($"Refresh {name,10} ... ");

        int random = new Random().Next();
        int delay = random % 1000   1000;
        await Task.Delay(delay);
        if (random % 2 == 0)
        {
            Console.ForegroundColor = ConsoleColor.Green;
            Console.Write($"OK");
            Console.ForegroundColor = DefaultColor;
        }
        else
        {
            Console.ForegroundColor = ConsoleColor.Red;
            Console.Write("KO");
            Console.ForegroundColor = DefaultColor;
        }
        Console.WriteLine($" ({delay,6} ms)");
    }
}
  

На данный момент это выполняется последовательно, но я бы хотел запускать каждую загрузку асинхронно. Проблема в том, что результаты не будут выводиться в соответствующую строку.

введите описание изображения здесь

Итак, мне интересно, как правильно выводить параллельные задачи на консоль. Я знаю, что это возможно, поскольку некоторые CLI уже делают это (docker, node). Мне также нужен счетчик для ожидающей загрузки. Нужно ли мне устанавливать курсор в начале и переписывать все?

Комментарии:

1. Означает ли -1, что это невозможно?

2. Вы можете установить положение курсора в определенное место и просто написать в этом месте. Можете ли вы показать пример, иллюстрирующий то, что вы пробовали? Вероятно, вы можете просто передать номер строки каждой задаче, а затем она может установить позицию и записать на консоль.

3. Кнопка downvote обычно используется, если кто-то не считает вопрос полезным, или если они считают, что автор не проводил никаких исследований, или если они считают, что вопрос неясен. Было бы неплохо, если бы участники, проголосовавшие против, оставили комментарий, чтобы указать, почему они проголосовали именно так, но я подозреваю, что это связано с отсутствием какого-либо кода.

4. @RufusL мой код — это просто цикл на Console.Write / Console.WriteLine . Я думал, что есть способ зарезервировать строку для каждой задачи. При перемещении курсора будет мигать дисплей :/

5. Вот пример кода, который имитирует то, что, я думаю, вы ищете. Существует метод, который принимает номер строки и описание строки, а затем записывает строку, как у вас в вашем примере. Он использует случайные числа для определения продолжительности каждой задачи и конечного результата (OK или KO). Затем основная программа запускает 4 задачи и ожидает их завершения. Вставьте его в новый проект и посмотрите, поможет ли это … используя задачи с консольным выводом