1. Thread usage
1. The program needs to execute and two or more tasks.
②. The program will wait for the occurrence of an event, such as user input, file operations, network operations, and search
③. Background Program
2. Concurrent execution of multiple threads
If multiple threads are running, there is only one single CPU. Which of the following is the actual execution?
① If a thread continuously occupies CPU resources for a long time and other resources cannot be executed,
The system will force the switch to execute other threads. (Forcible deprivation)
②. If a thread has nothing to do, the CPU can execute other threads. (Voluntarily give up)
③. This is determined by the scheduling mechanism of the operating system. different operating systems have different Scheduling Mechanisms.
Generally, the execution sequence of multiple threads cannot be accurately predicted. Special attention should be paid to the program design.
3. Create and start a thread
Threadstart thread startup delegate name = new threadstart (method name );
Thread thread Instance name = new thread (thread startup delegate name );
Thread Instance name. Start ();
4. Terminate the thread
①. Thread Instance name. Abort (); the consequence of using this method is that the thread cannot be recovered.
②. Thread Instance name. Interrupt (); can be recovered after interruption
5. Sleep thread
①. Thread Instance name. Sleep ();
When the thread sleep, the system immediately exits the execution queue for a period of time. When sleep ends, the system generates a clock interruption.
The thread is returned to the execution queue to resume the thread execution.
6. Suspend/restore the thread
①. Thread Instance name. Suspend (); suspended
Unlike the thread sleep, the thread suspension does not stop the thread immediately until the thread reaches the security point.
The thread is suspended. If the thread has not been started or has been stopped, it cannot be suspended.
②. Thread Instance name. Resume (); Recovery
Will cause a thread to jump out of the pending state and make the thread continue to run.
One thread cannot call sleep () for another thread, but one thread can call suspend () for another thread ().
You can also use many other methods to block threads. For example, you can call thread. Join to make one thread wait for another thread (sub-thread) to stop. Use monitor. Wait to make a thread wait for access to a synchronization object.
7. serialized threads
①. Thread Instance name. jion ();
For example, insert T. jion () in the main thread ();
After the main thread executes this statement, the main thread (the current thread) immediately enters the blocking status until T is finished running.
It is equivalent to inserting or concatenating t tasks into the main thread, and concatenating two clues into one clue.
8. thread locking mechanism
The thread locking mechanism ensures that only one thread can access Shared resources at a time.
Use the keyword lock
①. Lock statement syntax
Lock (Object Reference) Statement block;
②. Lock statement Function
When the object is locked, other threads accessing the thread will enter the waiting state.
③. The object lock mechanism ensures the integrity of Object Access: Only one thread can complete the operation before other threads can perform the operation.
④. Generally, when a thread writes a variable and other threads may read or write the variable
The locking mechanism should be used.
⑤. Thread Security
Thread security is to protect the security of the class members and code, so that they are not interrupted by several threads at the same time, using the locking mechanism.
6. When multiple threads share an object, the lock keyword should not be used. Here, monitor provides a solution for sharing resources by threads.
The monitor class can lock an object. A thread can operate on this object only when this lock is obtained.
For example:
Monitor. Enter (OBJ );
Monitor. Exit (OBJ );
7. critical section and lock
When talking about multi-threaded applications, the first thing we should think of is concurrency. Although this is useful for programs that execute multiple tasks at the same time, it is usually dangerous. To solve this problem, the concept of critical section and lock is put forward in C. In programming, a critical section is a region where only one process can enter at any time. In C #, the lock statement is used to declare the critical section. The code after the lock statement can be executed by a maximum of one process at a time, no matter whether it is a line or a piece of code.
9. The thread priority is unreliable. That is to say, priority cannot be used to control the thread execution sequence.
10. Background thread
①. What is a background thread? Compared with the main graphical user interface (GUI) threads of the application, these threads have a lower priority in different processes.
Running. Background threads are competent for tasks that cannot be executed immediately and do not want to wait. In C #,
If the isbackground attribute is set to true, this thread is the background thread.
There is only one difference between the background thread and the foreground thread, that is, the background thread does not prevent program termination. Once all foreground threads of a process are terminated,
CLR will call the abort () method of any surviving background process to completely terminate the process.
Note: The background thread cannot directly operate on data references outside the process.
②. How to communicate with the background thread? Use methodinvoker to delegate objects.
To use methodinvoker to delegate, three conditions are required:
A. Create a delegated background thread
Thread thread = new thread (New threadstart (run ));
Thread. isbackground = true; // set the thread as the background thread
Thread. Start ();
B. A Class-level method used as the interface between the background thread and the foreground visualization unit
Public void run ()
{
Int COUNT = 0;
Try
{
Methodinvoker MI = new methodinvoker (this. updatelabel );
// Create a delegate. updatelabel is the code managed by the delegate. It must be any method declared as void and does not accept any parameters.
While (true)
{
Count ++;
// This. Invoke (MI); // synchronous execution delegate
This. begininvoke (MI); // asynchronous execution delegate
Thread. Sleep (500 );
}
}
Catch (threadinterruptedexception E)
{
Console. writeline ("interruption exception in thread: {0}", e );
}
Catch (exception ex)
{
Console. writeline ("exception in thread: {0}", ex );
}
}
C. Visualization units that can be updated in an application
Public void updatelabel ()
{
Label1.text = count. tostring ();
}
Example 1: a multi-threaded typing exercise (vs2005)
Using system;
Using system. Collections. Generic;
Using system. componentmodel;
Using system. Data;
Using system. drawing;
Using system. text;
Using system. Windows. forms;
Using system. Threading;
/*
* Write an application based on Windows Forms to implement the typing exercise function. multithreading is required and used in the main thread.
* The timer control regularly generates a label control. Each label control displays a random letter, and each label is generated.
* A new thread (Auxiliary thread) is created to control the downward movement of the label control. The main thread monitors the keyboard.
* Input. If the text entered on the keyboard is the same as the text of the label control, the label disappears.
*/
Namespace typewriteexcercise
{
Public partial class frmtyped: Form
{
Public frmtyped ()
{
Initializecomponent ();
}
Private void frmtyped_load (Object sender, eventargs E)
{
Timer1.start (); // start the clock
}
Private void timereffectick (Object sender, eventargs E)
{
Label Label = new label (); // create a label object
Label. width = 12;
Label. Height = 12;
Label. forecolor = color. White; // set the foreground color of the label to white.
Label. backcolor = This. backcolor; // set the background color of the form to black.
This. Controls. Add (Label); // Add the label to the form.
System. Random random = new random (datetime. Now. Second * datetime. Now. Second );
// The square of the second of the current system time as the Random Seed
Label. Left = random. Next (this. width); // tag random number [0, width of the form ),
Letter = new letter (Label, this); // pass the tag and form to the letter object.
Threadstart = new threadstart (letter. Run); // create a thread to start the delegate. Note that the method name is in brackets.
Thread thread = new thread (threadstart); // create a thread instance
Thread. Start (); // start the thread
}
Private void frmtyped_keypress (Object sender, keypresseventargs E)
{
Foreach (Label label in this. Controls)
{
If (Label = NULL) // no label
{
Break; // exit
}
If (Label. Text [0] = E. keychar)
// Label. Text returns a string, and label. Text [0] returns the first character. E. keychar returns characters. In this way, all characters can be judged.
{
Label. Dispose (); // release all resources used by the label
This. Controls. Remove (Label); // remove the label from frmtyped
}
}
}
}
Public class letter
{
Private Label _ label;
Private form _ container;
Private int _ speed = 2;
Public letter (label Label, form container) // constructor accepts labels and forms
{
_ Label = label; // initialize the label
_ Container = container; // initialize the form
Random random = new random (datetime. Now. Second); // use the number of seconds of the current system time as the Random Seed
_ Speed = random. Next (5) + 1; // generates a random number [) to indicate the speed.
_ Label. Text = convert. tochar (65 + random. Next (57). tostring ();
/*
* A-z ascii code 97-122 A-Z ASCII code 65-90 [: 91/: 92]: 93 ^: 94 _: 95 ': 96
*/
Switch (_ speed)
{
Case 1:
_ Label. forecolor = color. Red; // set the foreground color of the label to red.
Break;
Case 2:
_ Label. forecolor = color. Yellow;
Break;
Case 3:
_ Label. forecolor = color. blue;
Break;
Case 4:
_ Label. forecolor = color. Green;
Break;
Case 5:
_ Label. forecolor = color. White;
Break;
Default:
_ Label. forecolor = color. White;
Break;
}
}
Public void run ()
{
Try
{
While (_ label. Top <= This. _ container. height + 100) // The top margin of the label is smaller than or equal to the height of the form + 100 pixels
{
If (_ label = NULL) // no label is generated.
{
Thread. currentthread. Abort (); // terminate the current thread.
}
_ Label. Top + = 1; // if there is a label, add 1 pixel to the top margin;
Thread. Sleep (_ speed * 5); // Let the thread sleep (the faster the speed, the shorter the sleep time. In milliseconds );
}
If (thread. currentthread. isalive) // if the current thread is still alive
{
Thread. currentthread. Abort (); // terminate the current thread.
}
}
Catch (exception ex)
{
Console. writeline ("error:" + ex. Message); // gets the message describing the current exception
Console. writeline ("error:" + ex. stacktrace); // obtain the string expression of frames on the call stack when the current exception occurs
}
Finally // release the resource. Whether or not an exception occurs, finally must be executed in five conditions.
{
If (! _ Label. Disposing) // If the tag is not released to the Process
{
_ Label. Dispose (); // release all resources used by tags
}
_ Container. Controls. Remove (_ label); // remove all tags generated in the form
}
}
}
}