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?
I believe that "what you're missing" is the integer division in the expression progress.Report(++complete / total * 100)
. When I replicated the issue this expression always evaluates to zero unless the total
variable is cast to a floating point variable type.
Other than that I was able to reproduce a mock version of your code with the desired outcome.
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));
}
}
}