Home > OS >  ProgressBar with IProgress<T> delegate across threads does not update
ProgressBar with IProgress<T> delegate across threads does not update

Time:12-05

I'm trying to display the progress of unzipping a few files on a WinForms ProgressBar.

Here I create a System.Progress with a handler that updates the ProgressBar

Progress<int> progress = new Progress<int>(value => {
    progressBar1.Value = value; progressBar1.Update(); }); 

Then I hand over my function to the thread pool.

Task t = Task.Run(() => FileUtils.UnzipTo(targetDir,
sourceDir, false, progress));

t.Wait();

Inside my unzip function I do this for every file in the archive:

progress.Report(  complete / total * 100);

This is definitely called and if I use a method for my handler the breakpoint is hit for every file (although too late I think)

I was hoping this would update the ProgressBar.

I see the dialog until the file is completely decompressed with a busy cursor above but there is no increase in progress.

What am I missing?

CodePudding user response:

I believe that "what you're missing" is the progress

public partial class MainForm : Form
{
    public MainForm()
    {
        InitializeComponent();
        buttonUnzip.Click  = onButtonUnzip;
    }
    private async void onButtonUnzip(object? sender, EventArgs e)
    {
        progressBar1.Visible = true;
        Progress<int> progress = new Progress<int>(value => {
            progressBar1.Value = value; progressBar1.Update();
        });
        await Task.Run(() => FileUtils.UnzipTo("mockSource", "mockDest", true, progress));
        progressBar1.Visible = false;
    }
}
class FileUtils
{
    static string[] GetFilesMock() => new string[25];
    static void UnzipOneMock(string sourceDir, string targetDir, string file) 
        => Thread.Sleep(TimeSpan.FromMilliseconds(100));
    public static void UnzipTo(
        string sourceDir,
        string targetDir,
        bool option, 
        IProgress<int> progress)
    {
        var files = GetFilesMock();
        int complete = 0;
        int total = files.Length;
        foreach (var file in files)
        {
            UnzipOneMock(sourceDir, targetDir, file);
            progress.Report((int)(  complete / (double)total * 100));
        }
    }
}
  • Related