Multithreading programming learning notes-Thread Pool (3), multithreading programming learning notes
Multi-thread programming learning notes-Thread Pool (1)
Multi-thread programming learning notes-Thread Pool (2)
5. Waiting for event processor and timeout in the thread pool
This example mainly describes how to implement timeout for operations in the thread pool and wait correctly in the thread pool.
The thread pool also has a ThreadPool. RegisterWaitForSingleObject. This method allows us to put the callback function into the queue in the thread pool. When the provided wait event processor receives a signal or times out, this callback function will be called to implement timeout for operations in the thread pool.
1. The Code is as follows:
Using System; using System. collections. generic; using System. diagnostics; using System. linq; using System. text; using System. threading; namespace ThreadTPLDemo {class Program {static void Main (string [] args) {Console. writeLine ("start to test the scheduled operation in the thread pool... "); TimesOperation (TimeSpan. fromSeconds (5); // provides an operation time of 5 seconds, and TimesOperation (TimeSpan. fromSeconds (9); // provides 9 seconds of operation time, working normally. writeLine ("................ "); Console. read ();} private static void TimesOperation (TimeSpan workTimes) {using (var manuEvt = new ManualResetEvent (false) {using (var cts = new CancellationTokenSource () {Console. writeLine ("start -- scheduled operation in the thread pool... "); Var work = ThreadPool. registerWaitForSingleObject (manuEvt, (state, isTimeOut) => AsyncOperWait (cts, isTimeOut), null, workTimes, true); Console. writeLine ("a long-running thread operation... "); ThreadPool. QueueUserWorkItem (_ => AsyncOper (cts. Token, manuEvt); Console. WriteLine ("... Run again in 2 seconds... "); Thread. sleep (workTimes. add (TimeSpan. fromSeconds (2); work. unregister (manuEvt) ;}} private static void AsyncOper (CancellationToken token, ManualResetEvent mrevt) {Console. writeLine ("start -- the first working thread in the thread pool... "); For (int I = 0; I <7; I ++) {if (token. isCancellationRequested) // determines whether the operation has been canceled {Console. writeLine ("using the polling method to cancel a working Thread ID: {0}", Thread. currentThread. managedThreadId); return;} Thread. sleep (TimeSpan. fromSeconds (1);} mrevt. set (); Console. writeLine ("------- the first working thread in the thread pool sends a signal ----------");} private static void AsyncOperWait (CancellationTokenSource cts, bool isTimeOut) {Console. writeLine ("start -- the second working line in the thread pool... "); If (isTimeOut) // determines whether the operation has been canceled {cts. Cancel (); Console. WriteLine (" The Working thread has timed out and canceled. ID: {0} ", Thread. CurrentThread. ManagedThreadId);} else {Console. WriteLine (" ------- the second worker Thread in the Thread pool has finished working ----------");}}}}
2. The program result is as follows.
After the program is started, some long-running operations are put in sequence. This operation runs for 6 seconds. If the operation is successful, a ManualResetEvent signal is set. If this operation is canceled, the operation is discarded.
We also registered the second asynchronous operation. When a signal is received from the ManualResetEvent object, this asynchronous operation will be called. If the first operation runs smoothly, a signal is set. If the first operation times out, CancellationToken is used to cancel the first operation.
Note: When a large number of operations in the thread pool are blocked, the above method is very useful.
6. Use a timer
Use the Threading. Timer object to implement asynchronous operations that are periodically called in the thread pool.
1. The Code is as follows:
Using System; using System. collections. generic; using System. diagnostics; using System. linq; using System. text; using System. threading; namespace ThreadPoolDemo {class Program {static Timer timer; static void Main (string [] args) {Console. writeLine ("start the test thread pool to run the operation through the timer, enter A to stop the timer... "); DateTime startTime = DateTime. now; timer = new Timer (_ => TimesOperation (startTime), null, TimeSpan. fromSeconds (1), TimeSpan. fromSeconds (2); Thread. sleep (6000); timer. change (TimeSpan. fromSeconds (2), TimeSpan. fromSeconds (4); Console. writeLine ("................ "); ConsoleKeyInfo key = Console. readKey (); if (key. key = ConsoleKey. a) {timer. dispose ();} Console. read ();} private static void TimesOperation (DateTime startTime) {TimeSpan time = DateTime. now-startTime; Console. writeLine ("Thread {0} has been running for {2} seconds since {1}", Thread. currentThread. managedThreadId, startTime. toString ("yyyy-MM-dd HH: mm: ss"), time. seconds );}}}
2. The program running result is as follows.
When the program starts, a timer is created first. The first parameter is the lambla expression and will be executed in the thread pool. The second parameter is null. Then, call the TimerOperation method, give an initial time, specify the time when TimerOperation will be run for the first time, and the subsequent call interval.
7. Use the BackgroundWorker component
This example uses the BackgroundWorker component to implement asynchronous operations.
When the program starts, A BackgroundWorker object instance is created, indicating that the background working thread supports canceling operations and operation progress notifications.
1. The Code is as follows:
Using System; using System. collections. generic; using System. componentModel; using System. diagnostics; using System. linq; using System. text; using System. threading; namespace ThreadTPLDemo {class Program {static Timer timer; static void Main (string [] args) {Console. writeLine ("start testing BackgroundWorker... "); BackgroundWorker bgwork = new BackgroundWorker (); bgwork. workerReportsProgress = true; bgwork. workersuppscanscancellation = true; bgwork. doWork + = worker_dowork; bgwork. progressChanged + = worker_ProgressChanged; bgwork. runWorkerCompleted + = worker_Completed; bgwork. runWorkerAsync (); // starts running the Console in the background. writeLine ("..... Enter C to cancel the BackgroundWorker background component ........... "); Do {lelekeyinfo key = Console. readKey (); if (key. keyChar. toString (). toUpper () = "C") {bgwork. cancelAsync () ;}} while (bgwork. isBusy); Console. read ();} static void worker_dowork (object sender, DoWorkEventArgs e) {Console. writeLine ("Thread {0} starts running", Thread. currentThread. managedThreadId); int result = 0; var bgwork = (BackgroundWorker) sender; for (int I = 0; I <100; I ++) {if (bgwork. cancel LationPending) // The background operation has been canceled {e. cancel = true; return;} if (I % 10 = 0) {bgwork. reportProgress (I); // display progress} Thread. sleep (200); result + = I;} e. result = result;} static void worker_ProgressChanged (object sender, ProgressChangedEventArgs e) {Console. writeLine ("Thread {0} has completed the workload of {1} %", Thread. currentThread. managedThreadId, e. progressPercentage);} static void worker_Completed (object sender, RunWorkerComple TedEventArgs e) {Console. WriteLine ("thread {0} has been executed! ", Thread. CurrentThread. ManagedThreadId); if (e. Error! = Null) {Console. writeLine ("Thread {0} error, error message: {1}", Thread. currentThread. managedThreadId, e. error. message);} else if (e. cancelled) {Console. writeLine ("Thread {0} has been canceled", Thread. currentThread. managedThreadId);} else {Console. writeLine ("Thread {0} is successfully executed and the result is: {1}", Thread. currentThread. managedThreadId, e. result );}}}}
2. The program ends normally, as shown in figure.
3. During program execution, manual intervention and cancellation are performed. For example. Please refer to the position of the yellow box. If I enter the letter C, the thread is canceled.
In the program, we define three events.