user3161402
user3161402

Reputation:

GUI freezes when text and progressbar changes

I'm creating a program that uses a TextBox and a ProgressBar and each time the text changes in the TextBox or the ProgressBar performs a step the GUI freezes and I can't do anything until the operation is done.

I know I need to run them on a different thread but I searched the entire web and didn't find a method that works for me.

This is an example when I write a file and I need to get the progress of it:

for (int l = 0; l < newfile.Length; l++)
{
  vfswriter.Write(newfile[l]);
  double percentage = ((double)l / (double)newfile.Length * 100);
  this.progressBar1.Value = int.Parse(Math.Truncate(percentage).ToString());
}

and this is an example when I change text:

this.richTextBox1.Text = "Installing patch : ";

Any help would be appreciated.

Upvotes: 1

Views: 776

Answers (2)

Selman Gen&#231;
Selman Gen&#231;

Reputation: 101701

Use a BackgroundWorker, put your for loop inside of DoWork method:

backgroundWorker1.DoWork += doWork;

private void doWork(object sender, DoWorkEventArgs e)
{
    for (int l = 0; l < newfile.Length; l++)
    {
       vfswriter.Write(newfile[l]);
       double percentage = ((double)l / (double)newfile.Length * 100);
       this.progressBar1.Value = int.Parse(Math.Truncate(percentage).ToString());
    }
}

When you want to execute your loop call backgroundWorker1.RunWorkerAsync() method.

Also you can use ProgressChanged event to update your progress bar:

backgroundWorker1.DoWork += doWork;
backgroundWorker1.ProgressChanged += progressChanged;

private void doWork(object sender, DoWorkEventArgs e)
{
    for (int l = 0; l < newfile.Length; l++)
    {
       vfswriter.Write(newfile[l]);
       double percentage = ((double)l / (double)newfile.Length * 100);
       var value = int.Parse(Math.Truncate(percentage).ToString());
       backgroundWorker1.ReportProgress(value);
    }
}

private void progressChanged(object sender, ProgressChangedEventArgs e)
{
    this.progressBar1.Value = e.ProgressPercentage;
}

Update: If you want to pass arguments to DoWork method you can do it when you calling the backgroundWorker1.RunWorkerAsync() method like this:

backgroundWorker1.RunWorkerAsync(argument);

And you can access it in DoWork method with the e.Argument. if you want to pass more than one argument you can do the trick with Anonymous Types.For example:

var myArguments = new { Property1 = "some value", Property2 = myId, Property3 = myList };
backgroundWorker1.RunWorkerAsync(myArguments);

In DoWork method:

dynamic arguments = e.Argument;
var arg1 = arguments.Property1;
var arg2 = arguments.Property2;
// and so on...

Upvotes: 3

jamesthollowell
jamesthollowell

Reputation: 1712

You could use the Task class to create and run background threads. A word of caution! Any time you want to update something from a thread that is not the main thread, you must use the Dispatcher to run code on the main thread.

My example code:

System.Threading.Tasks.Task task = new System.Threading.Tasks.Task(() =>
{
 for (int l = 0; l < newfile.Length; l++)
 {
   vfswriter.Write(newfile[l]);
   double percentage = ((double)l / (double)newfile.Length * 100);
   //This runs the code inside it on the main thread (required for any GUI actions
   App.Current.Dispatcher.Invoke((Action) (() =>
   {
     this.progressBar1.Value = int.Parse(Math.Truncate(percentage).ToString());
   }
 }
});
task.Start();

Upvotes: 0

Related Questions