Search code examples
c#7zipsevenzipsharp

C# extracting with sevenzipsharp and update progress bar without UI freeze


I'm having some problems with the file extraction. Everything works well with the progress bar output and the extraction. But when it is running the UI freezes. I've tried to use Task.Run() but then it doesn't really work well with the progress bar. Or maybe I just didn't use it correctly.

Any suggestions?

private void unzip(string path)
{
    this.progressBar1.Minimum = 0;
    this.progressBar1.Maximum = 100;
    progressBar1.Value = 0;
    this.progressBar1.Visible = true;
    var sevenZipPath = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), Environment.Is64BitProcess ? "x64" : "x86", "7z.dll");
    SevenZipBase.SetLibraryPath(sevenZipPath);

    var file = new SevenZipExtractor(path + @"\temp.zip");
    file.Extracting += (sender, args) =>
        {
            this.progressBar1.Value = args.PercentDone; 
        };
    file.ExtractionFinished += (sender, args) =>
        {
            // Do stuff when done
        };


    //Extract the stuff
    file.ExtractArchive(path);
}

Solution

  • You may want to look into the Progress<T> object in the .NET Framework - it simplifies adding progress reporting across threads. Here is a good blog article comparing BackgroundWorker vs Task.Run(). Take a look at how he is using Progress<T> in the Task.Run() examples.

    Update - Here is how it might look for your example. I hope this gives you a good enough understanding to be able to use the Progress<T> type in the future. :D

    private void unzip(string path)
    {
        progressBar1.Minimum = 0;
        progressBar1.Maximum = 100;
        progressBar1.Value = 0;
        progressBar1.Visible = true;
    
        var progressHandler = new Progress<byte>(
            percentDone => progressBar1.Value = percentDone);
        var progress = progressHandler as IProgress<byte>;
    
        Task.Run(() =>
        {
            var sevenZipPath = Path.Combine(
                Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location),
                Environment.Is64BitProcess ? "x64" : "x86", "7z.dll");
    
            SevenZipBase.SetLibraryPath(sevenZipPath);
    
    
            var file = new SevenZipExtractor(path);
            file.Extracting += (sender, args) =>
            {
                progress.Report(args.PercentDone);
            };
            file.ExtractionFinished += (sender, args) =>
            {
                // Do stuff when done
            };
    
            //Extract the stuff
            file.ExtractArchive(Path.GetDirectoryName(path));
        });
    }