RSS
 

Archive for the ‘Threading’ Category

Working With BackgroundWorker Part 2: Populating Treeviews

14 Apr

I ran into an issue the other day populating a Treeview with a bunch of data that took quite some time to retrieve. The problem wasn’t populating the tree, it was waiting for the data to come back, then populating the tree all at once that was bothering me. No one wants to wait forever for the treeview to become available. I figured a backgroundworker would be extremely useful at a time like this…

Let’s start by creating a simple method called PopulateTree and generating a BackgroundWorker… Make sure you generate the missing methods


private void PopulateTreeView()

{

BackgroundWorker bw = new BackgroundWorker();

bw.WorkerReportsProgress = true;

bw.WorkerSupportsCancellation = false;

bw.DoWork += new DoWorkEventHandler(bw_DoWork);

bw.ProgressChanged += new ProgressChangedEventHandler(bw_ProgressChanged);

bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw_RunWorkerCompleted);

You should already have a TreeView added to the Form. Lets just call it treeView1 for now. What we will do is populate the treeview with nodes 0 – a given number passed into the bw_DoWork method


//continuing inside the PopulateTreeView method

bw.RunWorkerAsync(10000);

}

//Now inside of our bw_DoWork method

void bw_DoWork(object sender, DoWorkEventArgs e)

{

//This is where the work you want the backgroundworker to do will be preformed

//DO NOT UPDATE THE GUI FROM HERE!

//The sender is the Background worker that called this Do Work

//Lets safely cast the backgroundwoker to bw

BackgroundWorker bw = sender as BackgroundWorker;

//The argument passed in is the number we want to count to.

int countTo = int.Parse(e.Argument.ToString());

//Loop through the numbers adding each one to the listview

for (int i = 1; i < countTo; i++)

{

//Calculate the percentage of numbers gone through

double percentComplete = (double) i / countTo) * 100;

//Report our progress

//This is where we tell the UI to update

//Lets pass the percentage and the number we want to add to the listview

bw.ReportProgress((int)percentComplete,i);

//Found it best to sleep for 1ms so the ui can update itself.

System.Threading.Thread.Sleep(1);

}

}

void bw_ProgressChanged(object sender, ProgressChangedEventArgs e)

{

//This is where progress from the bw will be handled

//You CAN update the UI from this method.

int progressComplete = e.ProgressPercentage;

//this is the number to add to the TreeView

int number = (int)e.UserState;

treeView1.Nodes.Add(number.ToString());

}

So, basically what we did here was boxed up an int and sent it through background workers ReportProgress method and unboxed that number inside the ProgressChanged method, then added it to our listview.

This is the proper way to update the UI from a backgroundworker. What’s great is we are not limited to sending a single object through the report progress, we could send a collection or even any object through that… Part III will show an example of something more complex. This is a good start though.

Download Source BackgroundWorkers Populate Treeview

 
No Comments

Posted in C#, Threading

 

Working with BackgroundWorkers Part 1

24 Mar

One of the first things I attempted in C# was threading. Being tired of my vbscript and javascript applications freezing, I decided to learn all I could about it. Learning threading led to my first C# application and a major headache… until I ran into the eBook “Threading in C#” by Joseph Albahari. If you want to learn threading go here download the book and read it cover to cover. I swear it’s the best thing you will do.

After writing a complex program full of threads and issues I stumbled upon the windows control backgroundWorker. I then cussed aloud and removed about 75% of my old code and replaced it with this wonderful control. That’s what inspired me to post this today. I am going to go over the windows background worker and explain a few of the do’s and don’ts that will hopefully save a few headaches. I have limited time so it’s going to be done in parts. Part 1 consists of a basic overview.

Let’s get started.

BackgroundWorker bw = new BackgroundWorker;

The above code will create a background worker, or you can simple drag and drop one onto your windows form.

The background worker consists of Three events that you will handle, these events are the bread and butter to the background worker. They are as follows.

bw.DoWork += new DoWorkEventHandler(bw_DoWork);
bw.ProgressChanged += new ProgressChangedEventHandler(bw_ProgressChanged);
bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw_RunWorkerCompleted);
return bw;

We now need to add the event methods.

void bw_DoWork(object sender, DoWorkEventArgs e){
//This is where the work you want the backgroundworker
//to do will be preformed

//DO NOT UPDATE THE GUI FROM HERE!

}

The DoWork method is where the background worker will do all of the work. .Net is smart and will launch the DoWork method in a seperate thread making threading simple, there is no need to implement your own threading! That being said… This DoWork method is being ran on a different thread! that means you Can’t update the user interface from this method, don’t try it, don’t even think about doing it! you will however and you will see what happens. Updating the UI needs to be done differently, and we will get to that.

The next method ProgressChanged

void bw_ProgressChanged(object sender, ProgressChangedEventArgs e)

{       //This is where progress from the bw will be handled

//You CAN update the UI from this method.

}

Yes, this is where you can update the user interface, It’s not as easy as you would like it I know but that’s the sad truth of threading. However you would be amazed at how easy the BackgroundWorker makes it compared to conventional threading.

The final Event is WorkCompleted

void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)

{

//Cleanup anything

//Update the UI if needed.

}

Here you cleanup everything you need to and update the UI if needed. Very straightforward.
What have we learned up until now? Not much except the 3 major events and the law “DO NOT UPDATE THE UI FROM THE DOWORK METHOD”

Part II contains an a working example.

 
No Comments

Posted in C#, Threading