尝试异步显示进度条,但进度条覆盖了以前的 C# 控制台应用程序

Trying to show Progress Bar with asynchronously, but progress bar override the previous C# console application

提问人:sandy 提问时间:4/21/2023 最后编辑:Theodor Zouliassandy 更新时间:4/21/2023 访问量:323

问:

public class test
{
    private static readonly object _lock = new object();
    public static async Task DrawProgressBar(int complete, int maxVal, int barSize,
        char progressCharacter)
    {
        lock (_lock)
        { 
            Console.CursorVisible = false;
            int left = Console.CursorLeft;
            decimal perc = (decimal)complete / (decimal)maxVal;
            int chars = (int)Math.Floor(perc / ((decimal)1 / (decimal)barSize));
            string p1 = String.Empty, p2 = String.Empty;

            for (int i = 0; i < chars; i++) p1 += progressCharacter;
            for (int i = 0; i < barSize - chars; i++) p2 += progressCharacter;

            Console.ForegroundColor = ConsoleColor.Green;
            Console.Write(p1);
            Console.ForegroundColor = ConsoleColor.DarkGreen;
            Console.Write(p2);

            Console.ResetColor();
            Console.Write(" {0}%", (perc * 100).ToString("N2"));
            Console.CursorLeft = left;
        }
    }

    public static async Task Main()
    {
        string[] files = new string[] { "file1.txt", "file2.txt", "file3.txt" };
        var  tasks = new List<Task>();
         
        for (int i = 0; i < files.Length; i++)
        {
            Console.SetCursorPosition((1 * i), 2 * i);
            Console.WriteLine("Processing file {0} of {1}: {2}",
                i + 1, files.Length, files[i]);
            Task t  = Task.Run(() => { Download(); });
            tasks.Add(t);
        }
        await  Task.WhenAll(tasks);
        Console.WriteLine();
    }

    private static async Task Download()
    {
        for (int j = 0; j <= 100 - 1; j++)
        {
            DrawProgressBar(j , 100, 50, '=');
            System.Threading.Thread.Sleep(100);
        }
    }
}

可以错过一些我错过的点。

C# 异步 .net-core async-await task-parallel-library

评论

0赞 Kozydot 4/21/2023
您的进度条重叠,因为未针对并发更新正确管理控制台输出
0赞 sandy 4/21/2023
同意,如果你有具体的例子,它很有帮助。
0赞 Kozydot 4/21/2023
结合使用 SemaphoreSlim 和 Console.SetCursorPosition 来确保一次只更新一个进度条,并且每次更新的光标位置正确
0赞 sandy 4/21/2023
我会尝试上面的建议。
1赞 Theodor Zoulias 4/21/2023
这些方法是否生成了有关缺少运算符的方法的编译警告?DrawProgressBarDownloadasyncawait

答:

1赞 Frenchy 4/21/2023 #1

按照不同的建议,我刚刚编写了这段代码,似乎还可以。

我认为使用更好......IAsyncEnumerable

static private readonly object _sync = new object();

static async Task Main(string[] args)
{
    var colors = new List<Enum> 
    { 
        ConsoleColor.DarkBlue,ConsoleColor.Red, ConsoleColor.Yellow, 
        ConsoleColor.Green, ConsoleColor.DarkGray, ConsoleColor.Blue
    };
    char[] symbol = new char[] { '#', '\u25A0', '\u2592', '\u2588', '\u2551', '\u2502' };
    var min = 0;
    var max = 100;
    var tasks = Enumerable.Range(0, 6).Select(async p =>
    {
        await foreach (var i  in DoJob(p))
        {
            Update(i, (p + 1) * 3, min, max, colors[p], symbol[p]);  
        }
    });
    await Task.WhenAll(tasks);

    Console.Read();
}

private static async IAsyncEnumerable<int> DoJob(int p)
{
    for (int i = 0; i <= 100; i++)
    {
        await Task.Delay(50 + p * 25);//Simulate waiting for data to come through. 
        yield return i;
    }
}
private static void Update(int value, int row, int min, int max, Enum _color, char symbol)
{
    // Calculate the percentage complete
    var percentComplete = (double)(value - min) / (max - min);

    // Calculate the width of the progress bar
    var width = Console.WindowWidth - 10;
    var progressWidth = (int)(percentComplete * width);
    lock (_sync)
    {
        // Set the cursor position and color
        Console.SetCursorPosition(0, row);
        Console.ForegroundColor = (ConsoleColor)_color;
        // Write the progress bar
        Console.Write("[{0}{1}] {2:P0}", new string(symbol, progressWidth), new string(' ', width - progressWidth), percentComplete);

        // Reset the color
        Console.ResetColor();
    }
}

结果:enter image description here