Aman
Aman

Reputation: 602

C# ProgressBar Freezing

I'm trying to calculatethe md5 hash of a file and put it in a textBox, I also have a ProgressBar that should keep running while the hash if being calculated, I set the ProgressBar to Marquee, and the bar will run while I select a file but as soon as the hash calculation starts the bar freezes until it is done. Here is my code:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;


namespace Calcula_MD5_BAR
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            Stopwatch timer = new Stopwatch();
            var openFileDialog1 = new OpenFileDialog();
            progressBar1.Style = ProgressBarStyle.Marquee;
            progressBar1.MarqueeAnimationSpeed = 30;  
            if (openFileDialog1.ShowDialog() == DialogResult.OK)
            {      
                timer.Start();
                textBox1.Text = GetFileMD5Hash(openFileDialog1.FileName);
                timer.Stop();
                lblTime.Text = timer.Elapsed.ToString();
                progressBar1.Style = ProgressBarStyle.Continuous;
                progressBar1.Increment(100);
            }
            progressBar1.MarqueeAnimationSpeed = 0;
        }

        protected string GetFileMD5Hash(string nomeArquivo)
        {
            FileStream file = new FileStream(nomeArquivo, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
            MD5 md5 = new MD5CryptoServiceProvider();
            byte[] retVal = md5.ComputeHash(file);
            file.Close();

            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < retVal.Length; i++)
            {
                sb.Append(retVal[i].ToString("x2"));
            }
            return sb.ToString();
        }



    }
}

Upvotes: 1

Views: 5468

Answers (2)

Servy
Servy

Reputation: 203830

You need to do your non-UI work in a non-UI thread. await helps with making the asynchrony of offloading work to another thread and marshaling the result back to the UI thread much easier to work with:

private async void button1_Click(object sender, EventArgs e)
{
    Stopwatch timer = new Stopwatch();
    var openFileDialog1 = new OpenFileDialog();
    progressBar1.Style = ProgressBarStyle.Marquee;
    progressBar1.MarqueeAnimationSpeed = 30;  
    if (openFileDialog1.ShowDialog() == DialogResult.OK)
    {      
        timer.Start();
        textBox1.Text = await Task.Run(() => 
            GetFileMD5Hash(openFileDialog1.FileName));
        timer.Stop();
        lblTime.Text = timer.Elapsed.ToString();
        progressBar1.Style = ProgressBarStyle.Continuous;
        progressBar1.Increment(100);
    }
    progressBar1.MarqueeAnimationSpeed = 0;
}

Upvotes: 4

toATwork
toATwork

Reputation: 1377

Use a background worker! Complete example can be found here (pasted below!):

http://www.codeproject.com/Tips/83317/BackgroundWorker-and-ProgressBar-demo

Just set the style to marquee

    public partial class Form1 : Form
    {
            public Form1()
            {
                    InitializeComponent();
                    Shown += new EventHandler(Form1_Shown);

                    // To report progress from the background worker we need to set this property
                    backgroundWorker1.WorkerReportsProgress = true;
                    // This event will be raised on the worker thread when the worker starts
                    backgroundWorker1.DoWork += new DoWorkEventHandler(backgroundWorker1_DoWork);
                    // This event will be raised when we call ReportProgress
                    backgroundWorker1.ProgressChanged += new ProgressChangedEventHandler(backgroundWorker1_ProgressChanged);
            }
            void Form1_Shown(object sender, EventArgs e)
            {
                    // Start the background worker
                    backgroundWorker1.RunWorkerAsync();
            }
            // On worker thread so do our thing!
            void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
            {
                    // Your background task goes here
                    for (int i = 0; i <= 100; i++)
                    {
                            // Report progress to 'UI' thread
                            backgroundWorker1.ReportProgress(i);
                            // Simulate long task
                            System.Threading.Thread.Sleep(100);
                    }
            }
            // Back on the 'UI' thread so we can update the progress bar
            void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
            {
                    // The progress percentage is a property of e
                    progressBar1.Value = e.ProgressPercentage;
            }
    }

Upvotes: 1

Related Questions