Recently, I've had a little bit of time and started playing with Visual Studio .NET 2005 again. One of the features that I really like is the BackgroundWorker Class. Now, you could always create your own background thread and process whatever you felt like with it, but it got a lot easier.
People like Jon Skeet have long advocated that all data access processing be facilitated in another thread other than the main UI thread. There are many benefits to this type of approach but it invites the inherent difficulty of using threading. In this article, I'll work through a brief walkthrough of using the BackgroundWorker to fill a DataGrid.
One of the golden rules of using Winforms and Threading is that you don't touch anything created on one thread in another one. I'll touch upon this in a second....
First, all you really need to use the BackgroundWorker is dragging a component onto your form, and at a minimum adding code to handle the DoWork event. Look at the following code snippet:
| private void worker_DoWork(object sender, DoWorkEventArgs e) { using (SqlConnection cn = new SqlConnection(ConnectString)) { SqlCommand cmd = new SqlCommand("SELECT * FROM CUSTOMERS", cn); dt = new DataTable("Customers"); SqlDataAdapter da = new SqlDataAdapter(cmd); da.Fill(dt); } lock(dataGridView1){ dataGridView1.DataSource = dt; } } private void btnLoadData_Click(object sender, EventArgs e) { worker.RunWorkerAsync(); } |
| private void worker_DoWork(object sender, DoWorkEventArgs e) { using (SqlConnection cn = new SqlConnection(ConnectString)) { SqlCommand cmd = new SqlCommand("SELECT * FROM CUSTOMERS", cn); dt = new DataTable("Customers"); SqlDataAdapter da = new SqlDataAdapter(cmd); da.Fill(dt); } //Removed the code setting the datasource here. } private void btnLoadData_Click(object sender, EventArgs e) { worker.RunWorkerAsync(); } private void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) { //Will be called when the DoWork is completed LoadData(); } private void LoadData() { //No exceptions here. dataGridView1.DataSource = dt; } |