articles

Home / DeveloperSection / Articles / DataGrid using BackgroundWorker - C#

DataGrid using BackgroundWorker - C#

DataGrid using BackgroundWorker - C#

Shankar M40205 24-Feb-2013

Hi Friends, Today we will discuss in this article how to use Backgroundwalker control in C # and load records from the database table.

Introduction

BackgroundWorker is used to execute Intensive tasks (time-consuming) in Separate Thread so the User Interface (UI) does not freeze.
As the tasks are running in the background and might take a long time, it is necessary to show some custom messages and update the UI when the work is done.

Adding BackgroundWorker Control

To add a BackgroundWorker control on to the Form, Simply drag and drop the control from Tool-box on to the Form or double-click the control in Tool-box to add it to the Form.
The Control is then placed on to the System-tray

The BackgroundWorker control is highlighted in the circle which is placed on to the System tray.

BackgroundWorker Properties

The properties of a BackgroundWorker which you need to know are:

WorkerReportsProgress – Used to indicate Progress when a task is running.

WorkerSupportsCancellation – Indicates whether the background task can be cancelled.

IsBusy - Indicates that the background worker is performing an Asynchronous Operation/background task or not.

CancellationPending – This Indicates that the application has requested the cancellation of the background task.

BackgroundWorker Methods

The methods associated with a BackgroundWorker are

RunWorkerAsync – To Start the background task

CancelAsync -  To Stop the background task/Thread

ReportProgress – To Report Progress

BackgroundWorker Events

These are three events associated with a BackgroundWorker

 The DoWork event does the costly work of executing the background Thread.
The DoWork event is called upon when the RunWorkerAsync method is called.
Where the DoWorkEventArgs has properties e.Argument and e.Result
e.Argument – The Parameter reference to the BackgroundWorker received by RunWorkerAsync.
e.Result – This indicates whether BackgroundWorker did the processing.
ProgressChanged

The ProgressChanged event reports the progress done by the Thread. The ProgressChanged event is raised from the DoWork Event using ReportProgress() Method.

private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)

{
// To report BackgroundWorker Progress
}

Then ProgressChangedEventArgs e contains properties e.ProgressPercentage and e.UserState

e.ProgressPercentage – Gets the progress percentage of the background task that is sent as a parameter in ReportProgress() Method of the DoWork Event

e.UserStateGets the user state that is sent as part of ReportProgress() Method from DoWork Event

RunWorkerCompleted

The event is executed when the BackgroundWorker has completed the Task. The event is also triggered when the BackgroundWorker is failed to do the task assigned or intentionally cancelling the task.

private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)

{
//Executed Up on Completion of BackgroundTask/ Failure/ Cancellation of Operation
}

The RunWorkerCompletedEventArgs e has

e.Cancelled – Indicates that the BackgroundWorker Operation has been Cancelled.

e.Error – Error Occurred in the background Process execution

e.Result – Indicates the Result of the background Process execution.

 BackgroundWorker Example
Program
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Data.SqlClient;
using System.Threading; 
namespace BackGroundWorkerExample
{
    public partial class frmRetrive : Form
    {         SqlCommand Sqlcmd;
        string ConnString = "Data Source=ServerName; User id =YourDBUserName; Password =DBPwd;";  
        int TotalRecords; 
        public frmRetrive()
        {             InitializeComponent();
            // To report progress from the background worker we set this property
            backgroundWorker1.WorkerReportsProgress = true;
        } 
        private void frmRetrive_Load(object sender, EventArgs e)
        {
            btCancel.Enabled = false;
            statusStrip1.Visible = false;
            toolStripStatusLabel1.Visible = false; 
            dataGridView1.ColumnCount = 2;
            dataGridView1.Columns[0].Name = "Fiche No.";
            dataGridView1.Columns[0].Width = 150;
            dataGridView1.Columns[1].Width = 150;
            dataGridView1.RowHeadersWidth = 21;
            dataGridView1.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.EnableResizing;             dataGridView1.ColumnHeadersHeight = 23;
            dataGridView1.Columns[1].Name = "Employee Name";
        } 
        private void btExecute_Click(object sender, EventArgs e)
        {
            statusStrip1.Visible = true;
            toolStripStatusLabel1.Visible = true;
            toolStripProgressBar1.Maximum = GetTotalRecords(); 
            if (!backgroundWorker1.IsBusy)
            {
                RetriveTableData TObj = new RetriveTableData();
                dataGridView1.Rows.Clear();
                backgroundWorker1.RunWorkerAsync(TObj);
                btExecute.Enabled = false;
                btCancel.Enabled = true;
            }
        }
 
        private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
        {
            RetriveTableData Obj = (RetriveTableData)e.Argument;
            string SqlcmdString = "SELECT C_FICH,C_SITE FROM XT_FICH";
            SqlDataReader reader;
            int i = 1;
            try             {
                using (SqlConnection conn = new SqlConnection(ConnString))
                {
                    Sqlcmd = new SqlCommand(SqlcmdString, conn);
                    conn.Open();
                    reader = Sqlcmd.ExecuteReader(); 
                    if (reader.HasRows)
                    {                         while (reader.Read())
                        {
                            //int.Parse(reader["NO_IND"].ToString());                             Obj.EmpId = reader["C_FICH"].ToString();
                            Obj.EmpName = reader["C_SITE"].ToString();
                            Thread.Sleep(100);
                            // To Report progress.
                            backgroundWorker1.ReportProgress(i,Obj); 
                            if (backgroundWorker1.CancellationPending)
                            {                                 // Set the e.Cancel flag so that the WorkerCompleted event                                 // knows that the process was cancelled.                                 e.Cancel = true;                                 backgroundWorker1.ReportProgress(0);                                 return;
                            }
                            i++;
                        }
                        conn.Close();
                    }
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }  
        private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)         {
            if (!backgroundWorker1.CancellationPending)
            {                 RetriveTableData Obj = (RetriveTableData)e.UserState;
                dataGridView1.Rows.Add(Obj.EmpId.ToString(),Obj.EmpName.ToString());
                toolStripProgressBar1.Value = e.ProgressPercentage;
                toolStripStatusLabel1.Text = "Processing row.. " + e.ProgressPercentage.ToString() + " of " +TotalRecords;
            }
        } 
       private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)         {             if (e.Cancelled)
            { 
                toolStripStatusLabel1.Text = "Cancelled by User Intentionally...";
                toolStripProgressBar1.Value = 0;
            }
            // Check to see if an error occurred in the background process.
            else if (e.Error != null)
            {
                toolStripStatusLabel1.Text = e.Error.Message;
            }
            else
            {
                // BackGround Task Completed with out Error
                toolStripStatusLabel1.Text = " All Records Loaded...";
            } 
        } 
        private int GetTotalRecords()
        {
            SqlConnection con;
            SqlCommand cmd;
            try
            {
                using (con = new SqlConnection(ConnString))
                {
                    cmd = new SqlCommand("SELECT COUNT(*) FROM XT_FICH", con);
                    con.Open();
                    TotalRecords = int.Parse(cmd.ExecuteScalar().ToString());
                    con.Close();
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
            return TotalRecords;
        } 
        private void btCancel_Click(object sender, EventArgs e)
        {             if (backgroundWorker1.IsBusy)
            {
                backgroundWorker1.CancelAsync();
                btCancel.Enabled = false;
                btExecute.Enabled = true;
            }
        }
        public class RetriveTableData
        {
            public string EmpId;
            public string EmpName;
        } 
        private void frmRetrive_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (e.CloseReason == CloseReason.UserClosing)
            {
                if (backgroundWorker1.IsBusy)
                {
                    backgroundWorker1.CancelAsync();
                    btCancel.Enabled = false;
                    btExecute.Enabled = true;
                }             }
        }
    }
}
  Starting a BackgroundWorker Task

The BackgroundWorker DoWork is fired when the RunWorkerAsync method is called

private void btStart_Click(object sender, EventArgs e)

        {
            statusStrip1.Visible = true;
            toolStripStatusLabel1.Visible = true;
            toolStripProgressBar1.Maximum = GetTotalRecords();
 
            if (!backgroundWorker1.IsBusy)
            {
                RetriveTableData TObj = new RetriveTableData();
                dataGridView1.Rows.Clear();
     // Start the BackGround Thread to Execute
                backgroundWorker1.RunWorkerAsync(TObj);
                btStart.Enabled = false;
                btCancel.Enabled = true;
            }
        }

The btStart_Click Event here calls the RunWorkerAsync() Method to fire the DoWork Event of the BackgroundWorker which executes the time-consuming task at the background Thread.

Here pass RunWorkerAsync() an Object of RetriveTableData class.

         /// <summary>

        /// Trial Class for Example
        /// </summary>
        public class RetriveTableData
        {
            public string EmpId;
            public string EmpName;
        }

In the above code, we check to see that the BackgroundWorker is performing any task in the background using the backgroundWorker1. IsBusy Property. If not, we call the RunWorkerAsync Method to start executing the Thread.

BackgroundWorker Thread

The actual execution of the Thread Starts here       

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)

        {
            RetriveTableData Obj = (RetriveTableData)e.Argument;
            string SqlcmdString = "SELECT C_FICH,C_SITE FROM XT_FICH";
            SqlDataReader reader;
            int i = 1;
            try
            {
                using (SqlConnection conn = new SqlConnection(ConnString))
                {
                    Sqlcmd = new SqlCommand(SqlcmdString, conn);
                    conn.Open();
                    reader = Sqlcmd.ExecuteReader();
 
                    if (reader.HasRows)
                    {
                        while (reader.Read())
                        {
                            //int.Parse(reader["NO_IND"].ToString());
                            Obj.EmpId = reader["C_FICH"].ToString();
                            Obj.EmpName = reader["C_SITE"].ToString();
                            Thread.Sleep(100);
                            // To Report progress.
                            backgroundWorker1.ReportProgress(i,Obj);
 
                            if (backgroundWorker1.CancellationPending)
                            {
                                // Set the e.Cancel flag so that the WorkerCompleted event
                                // knows that the process was cancelled.
                                e.Cancel = true;
                                backgroundWorker1.ReportProgress(0);
                                return;
                            }
                            i++;
                        }
                        conn.Close();
                    }
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

 

The e.Argument  in RetriveTableData Obj = (RetriveTableData)e.Argument contains the Parameter reference to the BackgroundWorker that is received by RunWorkerAsync which we cast it explicitly to type RetriveTableData.

Then, we establish the connection with the Specified DataSource and read records from the Database using the SqlDataReader class. The reader.Read() reads/retrieve  the rows one-by-one  from the Database table.

Next, we Report the progress using the ReportProgress Method of the BackgroundWorker where we pass it an int variable I and RetriveTableData Obj which has the record number and the Obj contains the value of the record that is read recently.

Each time we increment the variable I to 1 to indicate the number of records being read.

// To Report progress.

backgroundWorker1.ReportProgress(i,Obj);

BackgroundWorker Progress

The ProgressChanged event of BackgroundWorker is fired when; the ReportProgress is called in from the DoWork Event.

private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)

        {
            if (!backgroundWorker1.CancellationPending)
            {
                 //Gets the user state that is sent as part of ReportProgress() Method from DoWork Event
                RetriveTableData Obj = (RetriveTableData)e.UserState;
               //Add the data to the dataGridView1
                dataGridView1.Rows.Add(Obj.EmpId.ToString(),Obj.EmpName.ToString());
                toolStripProgressBar1.Value = e.ProgressPercentage;
                toolStripStatusLabel1.Text = "Processing row.. " + e.ProgressPercentage.ToString() + " of " +TotalRecords;
            }
        }

  Here we get the UserState and add the data to the dataGridView1 and we set the toolStripProgressBar1 value to the progress percentage of the background task that is sent as parameter in ReportProgress() Method in DoWork Event.

Completion of Background Task

Upon, completion or Cancellation or failure of the Task the following event is raised.

private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)

        {
            if (e.Cancelled)
            { 
                toolStripStatusLabel1.Text = "Cancelled by User Intentionally...";
                toolStripProgressBar1.Value = 0;
            }
            // Check to see if an error occurred in the background process.
            else if (e.Error != null)
            {
                toolStripStatusLabel1.Text = e.Error.Message;
            }
            else
            {
                // BackGround Task Completed with out Error
                toolStripStatusLabel1.Text = " All Records Loaded...";
            }
 
        }

  If the BackgroundWorker Task is cancelled by the Application, then e. Cancelled is set to true and the block of code in it executed, The cancellation of Task is Sent from the DoWork Event to the RunWorkerCompleted Event. In DoWork Event, the piece of code to check that the Process was cancelled is

  if (backgroundWorker1.CancellationPending)

                            {
                                // Set the e.Cancel flag so that the WorkerCompleted event
                                // knows that the process was cancelled.
                                e.Cancel = true;
                                backgroundWorker1.ReportProgress(0);
                                return;
                            }
Cancellation of Background Task

The background Process is cancelled by the CancelAsync Method of the BackgroundWorker.

//To see that background Process is running a Process

          if (backgroundWorker1.IsBusy)
            {
                // Stop the Background Thread execution
                backgroundWorker1.CancelAsync();
                btCancel.Enabled = false;
                btStart.Enabled = true;
            }
Here, we check to see that BackgroundWorker is executing a Thread and Abort

the execution of Thread by calling the CancelAsync Method.

Conclusion

We have seen how to work with BackgroundWorker Control in C# Windows Form that executes an asynchronous Operation on a Separate Thread, and the Properties and events associated with a BackgroundWorker.


c# c# 
Updated 09-Sep-2020

Leave Comment

Comments

Liked By