Mpdreamz / shellprogressbar

ShellProgressBar - display progress in your console application
MIT License
1.43k stars 134 forks source link

Incorrect tick increase on main progress bar #56

Closed 112RG closed 4 years ago

112RG commented 4 years ago

Not sure if this is normal behavior or I am doing something wrong with my code, but when setting maxTicks to 41 and then run pbar.Tick() it increments the main bar incorrectly and gets to 100% at around tick 10-20 The tick is incremented when the chidlbar finishes so it will only tick 41 times https://i.imgur.com/lNGRRRC.gifv

Mpdreamz commented 4 years ago

@112madgamer mind sharing a small reproduction in code?

112RG commented 4 years ago

I feel like it could be me creating a child in a for loop but I don't see how that would affect pbar which is only created once


var pbar = new ProgressBar(pages.Count , title , options);

foreach (HtmlNode page in pages)
            {

                var childOptions = new ProgressBarOptions
                {
                    ForegroundColor = ConsoleColor.Yellow,
                    BackgroundColor = ConsoleColor.DarkYellow,
                    ProgressCharacter = '\u2593'
                };
                var child = pbar.Spawn(100, "page: " + page.Id, childOptions);

                try
                {
                    using (client)
                    {

                        client.DownloadProgressChanged += (o, args) =>
                        {
                            child.Tick(args.ProgressPercentage);
                        };
                        client.DownloadFileCompleted += (o, args) =>
                        {
                            pbar.Tick();
                            child.Dispose();
                        };
                    }

                }
                catch (WebException error)
                {
                    if (((HttpWebResponse)error.Response).StatusCode == HttpStatusCode.NotFound)
                    {
                        return;
                    }
                }
Mpdreamz commented 4 years ago

The following works for me:

var files = new string[]
{
    "https://github.com/Mpdreamz/shellprogressbar/archive/4.3.0.zip",
    "https://github.com/Mpdreamz/shellprogressbar/archive/4.2.0.zip",
    "https://github.com/Mpdreamz/shellprogressbar/archive/4.1.0.zip",
    "https://github.com/Mpdreamz/shellprogressbar/archive/4.0.0.zip",
};
var childOptions = new ProgressBarOptions
{
    ForegroundColor = ConsoleColor.Yellow,
    ProgressCharacter = '\u2593'
};
using var pbar = new ProgressBar(files.Length, "downloading");
foreach (var (file, i) in files.Select((f, i) => (f, i)))
{
    byte[] data = null;
    using var child = pbar.Spawn(100, "page: " + i, childOptions);
    try
    {
        using var client = new WebClient();
        client.DownloadProgressChanged += (o, args) => child.Tick(args.ProgressPercentage);
        client.DownloadDataCompleted += (o, args) => data = args.Result;
        client.DownloadDataAsync(new Uri(file));
        while (client.IsBusy)
            Thread.Sleep(1);

        pbar.Tick();
    }
    catch (WebException error)
    {
        pbar.WriteLine(error.Message);
    }
}

WebClient() is a bit finicky with async IO 😄

112RG commented 4 years ago

Just adding my updated code

try
{
     client.DownloadProgressChanged += (o, args) => child.Tick(args.ProgressPercentage);
     Console.WriteLine(imageurl.ToString());
     await client.DownloadFileTaskAsync(imageurl.ToString(), save_path + page.Id + ".png");
     pbar.Tick();
}

The trick seemed to be moving pbar.Tick() outside of client.DownloadFileCompleted