Reputation:
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
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
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