Simple use of BackgroundWorker to create multiple threads of tutorial _ Practical Tips

Source: Internet
Author: User
Tags thread stop

BackgroundWorker is a very good line program, can avoid the interface of suspended animation, let the thread to operate what you want to do, it is easy to learn, but can achieve a very powerful function. The purpose of this article is to publish the recently learned to share out, we exchange, of course, I am also a rookie, here you will learn to BackgroundWorker simple use, stop, pause, continue and other operations, BackgroundWorker is much simpler than thread and threadpool, in order to be more convenient to use in practical applications, I am using WinForm, not using the console program.

Drag a button and RichTextBox to the interface in the UI interface.

I will start with the simplest, only the simplest code will let people have the desire to continue to learn, the following code can be 1 to 999 print to the RichTextBox1 control.

Copy Code code as follows:

private void Button1_Click (object sender, EventArgs e)
{
Create a BackgroundWorker thread
BackgroundWorker bw = new BackgroundWorker ();
Create a DoWork event, specify the Bw_dowork method to do things
Bw. DoWork + = new Doworkeventhandler (bw_dowork);
Start execution
Bw. RunWorkerAsync ();
}

void Bw_dowork (object sender, DoWorkEventArgs e)
{
for (int i = 0; i < 1000; i++)
{
This.richTextBox1.Text + = i + Environment.NewLine;
}
}

Unfortunately, the above code will be an error, error message: Invalid thread operation: It is not accessed from a thread that is not creating the control "RichTextBox1".

So let's continue to transform the code so that the numbers are displayed on the RichTextBox1 control, and the RichTextBox1 focus is at the bottom end.

Copy Code code as follows:



private void Button1_Click (object sender, EventArgs e)


{


Create a BackgroundWorker thread


BackgroundWorker bw = new BackgroundWorker ();


Create a DoWork event, specify the Bw_dowork method to do things


Bw. DoWork + = new Doworkeventhandler (bw_dowork);


Start execution


Bw. RunWorkerAsync ();


}





void Bw_dowork (object sender, DoWorkEventArgs e)


{


for (int i = 0; i &lt; 1000; i++)


{


This. Invoke ((MethodInvoker) delegate


{


This.richTextBox1.Text + = i + Environment.NewLine;


});


}


}





private void Richtextbox1_textchanged (object sender, EventArgs e)


{


RichTextBox textbox = (RichTextBox) sender;





Textbox. SelectionStart = TextBox. Text.length;


Textbox. Scrolltocaret ();


}


Above is a simple example of BackgroundWorker, no more complicated code, this is BackgroundWorker, we add the Stop button, let the thread stop.

Then drag a button control to the interface to let the thread stop we first need to change the code so that the button event can also control the BackgroundWorker thread.

Copy Code code as follows:



BackgroundWorker bw = NULL;





private void Button1_Click (object sender, EventArgs e)


{


Create a BackgroundWorker thread


BW = new BackgroundWorker ();


Specifies that the thread can be stopped


Bw. Workersupportscancellation = true;


Create a DoWork event, specify the Bw_dowork method to do things


Bw. DoWork + = new Doworkeventhandler (bw_dowork);


Start execution


Bw. RunWorkerAsync ();


}





private void Button2_Click (object sender, EventArgs e)


{


Stop thread


Bw. CancelAsync ();


}





void Bw_dowork (object sender, DoWorkEventArgs e)


{


for (int i = 0; i &lt; 1000; i++)


{


Gets whether the current thread has a stop directive


if (BW). cancellationpending)


{


E.cancel = true;


Return


}





This. Invoke ((MethodInvoker) delegate


{


This.richTextBox1.Text + = i + Environment.NewLine;


});


}


}


In order to avoid the complexity of the code, the above code I did not do more experience changes, such as clicking the Start button, the Start button should be unavailable, click the Stop button after the Stop button is not available, activate the Start button.

Below we will continue to upgrade, how to know if the thread has been completed or the thread has stopped

Copy Code code as follows:



BackgroundWorker bw = NULL;





private void Button1_Click (object sender, EventArgs e)


{


BW = new BackgroundWorker ();


Bw. Workersupportscancellation = true;


Bw. DoWork + = new Doworkeventhandler (bw_dowork);


The thread completes or stops the event that occurs


Bw. runworkercompleted + = new Runworkercompletedeventhandler (bw_runworkercompleted);





Bw. RunWorkerAsync ();


}





private void Button2_Click (object sender, EventArgs e)


{


Bw. CancelAsync ();


}





void Bw_dowork (object sender, DoWorkEventArgs e)


{


for (int i = 0; i &lt; 1000; i++)


{


if (BW). cancellationpending)


{


E.cancel = true;


Return


}





This. Invoke ((MethodInvoker) delegate


{


This.richTextBox1.Text + = i + Environment.NewLine;


});


}


}





void Bw_runworkercompleted (object sender, Runworkercompletedeventargs e)


{


if (e.cancelled)


{


This.richTextBox1.Text + = "thread has stopped";


}


Else


{


This.richTextBox1.Text + = "Thread has been completed";


}


}


So far you can use BackgroundWorker to create a thread, you already know it, of course BackgroundWorker also have a reportprogress scroll bar event, can show progress, I think it is redundant, Because most of the progress can be bw_dowork to control the implementation. Below we continue to refine BackgroundWorker, add pause and Continue function.

Then drag a button control to the interface, BackgroundWorker pause and continue we use ManualResetEvent.

Copy Code code as follows:



BackgroundWorker bw = NULL;


Create ManualResetEvent


ManualResetEvent Mr = new ManualResetEvent (true);





private void Button1_Click (object sender, EventArgs e)


{


BW = new BackgroundWorker ();


Bw. Workersupportscancellation = true;


Bw. DoWork + = new Doworkeventhandler (bw_dowork);


Bw. runworkercompleted + = new Runworkercompletedeventhandler (bw_runworkercompleted);





Bw. RunWorkerAsync ();


}





private void Button2_Click (object sender, EventArgs e)


{


Bw. CancelAsync ();


}





private void Button3_Click (object sender, EventArgs e)


{


Button B = (button) sender;


if (B.text = "Paused")


{


Mr. Reset ();


B.text = "Continue";


}


Else


{


Mr. Set ();


B.text = "Pause";


}





}





void Bw_dowork (object sender, DoWorkEventArgs e)


{


for (int i = 0; i &lt; 1000; i++)


{


if (BW). cancellationpending)


{


E.cancel = true;


Return


}





This. Invoke ((MethodInvoker) delegate


{


This.richTextBox1.Text + = i + Environment.NewLine;


});





Accept Instructions


Mr. WaitOne ();


}


}





void Bw_runworkercompleted (object sender, Runworkercompletedeventargs e)


{


if (e.cancelled)


{


This.richTextBox1.Text + = "thread has stopped";


}


Else


{


This.richTextBox1.Text + = "Thread has been completed";


}


}


Most of the BackgroundWorker's functionality has been implemented so far, and the above code is found in many blogs, and only one background thread has been executed. If we have 1000 time-consuming tasks, then a thread is far from enough, we need to create a number of threads, let him execute, such as the creation of 10 threads, 1000 tasks divided into different parts and 10 threads to execute separately.

We use the List generic list<backgroundworker>, and then use BW. RunWorkerAsync (i) passes the parameters to the Bw_dowork and uses e.argument to accept the parameters in the Bw_dowork.

Copy Code code as follows:



list&lt;backgroundworker&gt; BWS = new list&lt;backgroundworker&gt; ();


int t = 10;





private void Button1_Click (object sender, EventArgs e)


{


for (int i = 0; i &lt; T; i++)


{


BackgroundWorker bw = new BackgroundWorker ();


Bw. DoWork + = new Doworkeventhandler (bw_dowork);


Bws. ADD (BW);





Bw. RunWorkerAsync (i);


}


}





void Bw_dowork (object sender, DoWorkEventArgs e)


{


Int J = Convert.ToInt32 (e.argument);


for (int i = j; I &lt; 1000 i = i + t)


{


if ((BackgroundWorker) sender). cancellationpending)


{


E.cancel = true;


Return


}





String item = String.Format ("Thread {0} is manipulating data {1}", J + 1, i);





This. Invoke ((MethodInvoker) delegate


{


This.richTextBox1.Text + = Item + Environment.NewLine;


});





Thread.Sleep (200);


}


}





Because the above code is not time-consuming operation, and opened the thread 10, too fast, causing the interface suspended animation state, you can use sleep to let the thread hibernate.

We continue to refine the code, join the stop operation, join the completion and stop the event, because it is multi-threaded, to judge whether the thread operation is complete and we use BWS. Remove (sender as BackgroundWorker); method to delete a thread and then use BWS. Count = = 0来 To determine if the operation is complete.

Copy Code code as follows:



list&lt;backgroundworker&gt; BWS = new list&lt;backgroundworker&gt; ();


int t = 10;





private void Button1_Click (object sender, EventArgs e)


{


for (int i = 0; i &lt; T; i++)


{


BackgroundWorker bw = new BackgroundWorker ();


Bw. DoWork + = new Doworkeventhandler (bw_dowork);


Bw. Workersupportscancellation = true;


Bw. runworkercompleted + = new Runworkercompletedeventhandler (bw_runworkercompleted);


Bws. ADD (BW);





Bw. RunWorkerAsync (i);


}


}





private void Button2_Click (object sender, EventArgs e)


{


for (int i = 0; i &lt; T; i++)


{


Bws[i]. CancelAsync ();


}


}





void Bw_dowork (object sender, DoWorkEventArgs e)


{


Int J = Convert.ToInt32 (e.argument);


for (int i = j; I &lt; 1000 i = i + t)


{


if ((BackgroundWorker) sender). cancellationpending)


{


E.cancel = true;


Return


}





String item = String.Format ("Thread {0} is manipulating data {1}", J + 1, i);





This. Invoke ((MethodInvoker) delegate


{


This.richTextBox1.Text + = Item + Environment.NewLine;


});





Thread.Sleep (200);


}


}





void Bw_runworkercompleted (object sender, Runworkercompletedeventargs e)


{


Bws. Remove (sender as BackgroundWorker);


if (BWS. Count = 0)


{


if (e.cancelled)


{


This.richTextBox1.Text + = "thread has stopped";


}


Else


{


This.richTextBox1.Text + = "Thread has been completed";


}


}


}


The above code in the stop is not to stop immediately, this is the same as driving, the faster the drive, the brake after the drag line longer, the same, the more open thread, the total pause required longer, I do not know whether the correct. In addition, I would also like to ask if all of the real thread stop, the point stopped after all threads immediately stop.

Below we continue to add pause and continue function, the same reason we use list<manualresetevent>.

Copy Code code as follows:



list&lt;backgroundworker&gt; BWS = new list&lt;backgroundworker&gt; ();


List&lt;manualresetevent&gt; Mrs = new List&lt;manualresetevent&gt; ();


int t = 10;





private void Button1_Click (object sender, EventArgs e)


{


for (int i = 0; i &lt; T; i++)


{


BackgroundWorker bw = new BackgroundWorker ();


Bw. DoWork + = new Doworkeventhandler (bw_dowork);


Bw. Workersupportscancellation = true;


Bw. runworkercompleted + = new Runworkercompletedeventhandler (bw_runworkercompleted);


Bws. ADD (BW);





Bw. RunWorkerAsync (i);





Mrs. ADD (New ManualResetEvent (true));


}


}





private void Button2_Click (object sender, EventArgs e)


{


for (int i = 0; i &lt; T; i++)


{


Bws[i]. CancelAsync ();


}


}





private void Button3_Click (object sender, EventArgs e)


{


Button B = (button) sender;


if (B.text = "Paused")


{


for (int i = 0; i &lt; Mrs. Count; i++)


{


Mrs[i]. Reset ();


}


B.text = "Continue";


}


Else


{


for (int i = 0; i &lt; Mrs. Count; i++)


{


Mrs[i]. Set ();


}


B.text = "Pause";


}


}





void Bw_dowork (object sender, DoWorkEventArgs e)


{


Int J = Convert.ToInt32 (e.argument);


for (int i = j; I &lt; 1000 i = i + t)


{


if ((BackgroundWorker) sender). cancellationpending)


{


E.cancel = true;


Return


}





String item = String.Format ("Thread {0} is manipulating data {1}", J + 1, i);





This. Invoke ((MethodInvoker) delegate


{


This.richTextBox1.Text + = Item + Environment.NewLine;


});





Thread.Sleep (200);


MRS[J]. WaitOne ();


}


}





void Bw_runworkercompleted (object sender, Runworkercompletedeventargs e)


{


Bws. Remove (sender as BackgroundWorker);


if (BWS. Count = 0)


{


if (e.cancelled)


{


This.richTextBox1.Text + = "thread has stopped";


}


Else


{


This.richTextBox1.Text + = "Thread has been completed";


}


}


}


So far, all the code has been, multiple threading operation will bring a lot of trouble, such as multiple threads at the same time to write data to a file, multi-threaded update DataTable, etc., will make the software inexplicably automatic exit. net2.0 there is no absolute thread-safe data set, a lot of big guys are said to use lock, but I am also a little understanding of lock, please enlighten us, such as on what the wrong, but also please a lot of guidance.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.