Multi-threaded application summary and multi-threaded application Summary
I. Several Methods of Multithreading
BeginXXX and EndXXX methods for other components
Other. net components also have methods similar to BeginInvoke and EndInvoke, such as the BeginGetResponse and EndGetResponse methods of the System. Net. HttpWebRequest class. The usage is similar to the Delegate-type BeginInvoke and EndInvoke methods, for example:
Class Program
{
// Callback function
Private static void requestCompleted (IAsyncResult asyncResult)
{
If (asyncResult = null | asyncResult. AsyncState = null)
{
Console. WriteLine ("Callback failed ");
Return;
}
HttpWebRequest hwr = asyncResult. AsyncState as HttpWebRequest;
HttpWebResponse response = (HttpWebResponse) hwr. EndGetResponse (asyncResult );
StreamReader sr = new StreamReader (response. GetResponseStream ());
String str = sr. ReadToEnd ();
Console. WriteLine ("Returned stream Length:" + str. Length );
}
Static void Main (string [] args)
{
HttpWebRequest request =
(HttpWebRequest) WebRequest. Create ("http://www.baidu.com ");
// Asynchronous request
IAsyncResult asyncResult = request. BeginGetResponse (requestCompleted, request );
Console. WriteLine ("task start ");
Console. Read ();
}
}
Ii. Thread Status Control
Status Control of the thread initiated by the delegate
The EndInvoke method of the delegate stops the current thread from running until the asynchronous execution of the delegate is completed.
The IAsyncResult. IsCompleted attribute indicates whether the asynchronous execution of the delegate is completed.
The entrusted WaitOne method waits for the Asynchronous Method to be executed.
3. Processing of multi-threaded GUI access
Use the BackgroundWorker component
Main events and parameters:
1. DoWork-this event is triggered when the BackgroundWorker. RunWorkerAsync method is executed and the DoWorkEventArgs parameter is passed;
2. progressChanged-Changes in the processing status obtained during Operation Processing, through BackgroundWorker. the ReportProgress method triggers this event and passes ProgressChangedEventArgs, which contains the percentage of processing. This parameter is used to set the progressbar control on the UI.
3. RunWorkerCompleted: this event is triggered when the asynchronous operation is completed or terminated midway through. To terminate the background operation in advance, you can call the BackgroundWorker. CancelAsync method. Detects BackgroundWorker in the function that handles DoWork events. whether the CancellationPending attribute is true. If it is true, it indicates that the asynchronous call has been canceled and DoWorkEventArgs. the Cancel attribute is set to true (the second parameter passed to the function for processing DoWork events), so that when the asynchronous call is exited, you can let the function that handles the RunWorkerCompleted event know whether to exit normally or midway through.
Main Methods:
1. backgroundWorker. the RunWorkerAsync-"start" Asynchronous call method has two reloads: RunWorkerAsync () and RunWorkerAsync (object argument). The second overload provides a parameter for asynchronous calls. (If multiple parameters need to be passed, use a class to pass them ). After this method is called, The DoWork event is triggered, and the DoWorkEventArg parameter is passed to the function for processing the DoWork event, which contains the parameters passed by RunWorkerAsync. You can perform complex operations in the corresponding DoWork processing functions.
2. backgroundWorker. reportProgress-The ReportProgress (int percent) can be called to continuously report the progress in a lengthy operation. When the ReportProgress method is called, The ProgressChanged event is triggered. Provides an integer between 0 and 100, which indicates the percentage of background activities completed. You can also provide any object as the second parameter, allowing you to pass status information to the event handler. As the ProgressChangedEventArgs parameter attribute passed to this process, the percentage and your own object (if provided) will be passed to the ProgressChanged event handler. These attributes are named ProgressPercentage and UserState respectively, and your event handler can use them in any way you need. (Note: This method is only available when the BackgroundWorker. WorkerReportsProgress attribute is set to true ).
3. BackgroundWorker. CancelAsync-this method is called when you need to exit the asynchronous call. However, this is not enough because it only sets the BackgroudWorker. CancellationPending attribute to true. You need to constantly check whether BackgroudWorker. CancellationPending is true during asynchronous call processing. If it is true, exit. (Note: This method is only available when the BackgroundWorker. workersuppscanscancellation attribute is set to true ).
// Button event
Private void button#click (object sender, EventArgs e)
{
This. backgroundWorker1.RunWorkerAsync (); // process the transaction
}
// Process transaction events
Private void backgroundworker=dowork (object sender, DoWorkEventArgs e)
{
// Initialization progress bar
This. progressbarriers 1.maximum = 100;
This. progressBar1.Minimum = 0;
// Simulate Transaction Processing
For (int I = 0; I <100; I ++)
{
Thread. Sleep (10 );
// Triggered by a local operation completion event
This. backgroundWorker1.ReportProgress (I, null );
}
}
// Method for executing partial operations
Private void backgroundWorker1_ProgressChanged (object sender, ProgressChangedEventArgs e)
{
This. progressBar1.Value = e. ProgressPercentage; // you can specify the progress bar value.
}
// Triggered when transaction processing is complete
Private void backgroundworkerappsrunworkercompleted (object sender, RunWorkerCompletedEventArgs e)
{
MessageBox. Show (null, "the worker thread is finished! "," Prompt ");
}
4. Thread Pool
Use of Thread Pool
Class Program
{
// Thread method
Public static void ThreadProc (object I)
{
Console. WriteLine (I. ToString ());
Thread. Sleep (1000 );
}
Public static void Main ()
{
ThreadPool. SetMaxThreads (3, 3); // you can specify a thread pool.
For (int I = 0; I <10; I ++)
{
ThreadPool. QueueUserWorkItem (new WaitCallback (ThreadProc), "Thread" + I );
}
Console. WriteLine ("Running ended ");
Console. Read ();
}
}
Every process has a thread pool. The default thread pool size is 25. We can set its maximum value through the SetMaxThreads method.
Note: Because the prototype of the WaitCallback delegate is void WaitCallback (object state), there is no way to encapsulate multiple parameters into one Object.
5. Thread Synchronization
Use Semaphore
Semaphore: specifies the number of threads that can simultaneously access a resource or resource pool.
Class Program
{
Private static Semaphore semaphore = new Semaphore (0, 5); // initialize the Semaphore
Static void Main (string [] args)
{
For (int I = 0; I <10; I ++)
{
Thread thread = new Thread (Method );
Thread. Start ("thread" + I );
}
Semaphore. Release (2); // Release 2 semaphores
Console. WriteLine ("the main thread has finished running! ");
Console. Read ();
}
// Thread execution Method
Private static void Method (object o)
{
Semaphore. WaitOne (); // wait for the semaphore
Thread. Sleep (1000 );
Console. WriteLine (o. ToString ());
Semaphore. Release (); // Release the semaphore
}
}
Other threads can be executed only when the main thread is released. Because the initial value of the semaphore counter is 0, other threads will be blocked before the main thread is released. Then, I directly use the Release (2) function in the main thread to set the counter to 2, so the two threads can be executed simultaneously.
Note:You can set a name for the semaphore, which is visible to the operating system. Therefore, you can use these semaphores to coordinate resource usage across process boundaries.
Class Program
{
Static void Main (string [] args)
{
// Five initial semaphores, up to 10 semaphores
Semaphore seamphore = new Semaphore (5, 10, "Test ");
Seamphore. WaitOne (); // wait for a signal
Console. WriteLine ("Get semaphore 1 ");
Seamphore. WaitOne (); // wait for a signal
Console. WriteLine ("Get semaphore 2 ");
Seamphore. WaitOne (); // wait for a signal
Console. WriteLine ("getting semaphores 3 ");
Console. WriteLine ("the main thread has finished running! ");
Console. Read ();
}
}
Run two such programs. The result is as follows. In the second running example, the program will be blocked on the third semaphore:
Vi. Timer