Analysis of multi-threaded programming under .NET
Www.chinacs.net Chinese C # Technology Station
Multithreading is the characteristics of many operating systems, which greatly improves the operational efficiency of the program, so multi-threaded programming technology is widely concerned for programmers. At present, Microsoft's .NET strategy is further promoted, and various related technologies are accepting the majority of programming, and the multi-thread programming technology is equivalent to multi-thread programming technology in .NET. I will introduce you to the basic methods and steps of multithreading programming under .NET.
Start new thread
Creating a new thread under .NET is very easy, you can start a new thread through the following statement:
Thread thread = new thread (New Threadstart (threadfunc));
Thread.start ();
The first statement creates a new THREAD object and indicates a method of this thread. When the new thread starts, the method is called executed. This thread object calls the thread method to call by a case-secure method through an instance of a System..threading.ThreadStart class.
The second statement officially begins the new thread. Once the method start () is called, the thread is kept in a "alive" state, you can determine if it is in the "Alive" state by reading its isalive property . The following statement shows how the thread hangs this thread if a thread is in the "Alive" state:
IF (thread.isalive) {
Thread.suspend ();
}
However, please note that the start () method of the thread object is just starting the thread without ensuring that its thread method threadfunc () can be implemented immediately. It simply ensures that the thread object can be assigned to the CPU time, and the actual execution is also determined by the operating system according to the processor time.
A thread method does not contain any parameters, and no value is returned. Its naming rules are the same as the naming rules of the general function. It can either static (static) or nonStatic. When it is executed, the corresponding thread is over, and the IsAlive property of its thread object is set to false. Below is an example of a thread method:
Public static void threadfunc ()
{
For (int i = 0; i <10; i ) {
Console.writeline ("Threadfunc {0}", i);
}
}
Front desk thread and background thread
COMMON LANGUAGE RUNTIME, CLR can distinguish between two different types of threads: front desk threads and background threads. The difference between the two is: The application must run all the front desk threads to exit; and for the background thread, the application can not consider whether it has been running directly, all the background threads will be exited when the application exits. Auto end.
A thread is the front desk thread or the background thread can be determined by its IsBackground properties. This attribute is readable and writable. Its default value is false, which means a thread defaults to the front desk thread. We can set it to TRUE to make it a backbone thread.
The following example is a console program that starts 10 threads at first, and each thread runs for 5 seconds. Since the ISBackground attributes of the thread defaults to False, they are all reception threads, so although the main thread of the program is running soon, the program is running to all started threads will end. The sample code is as follows:
Using system; using system.threading;
Class myapp
{
Public static void main ()
{
For (int i = 0; i <10; i ) {
Thread thread = new thread (New Threadstart (threadfunc));
Thread.start ();
}
}
Private static void threadfunc ()
{
DateTime start = datetime.now;
While (DateTime.Now - Start). Seconds <5)
;
}
}
Next, we slightly modifications to the above code, set the ISBACKGROUND attribute of each thread to True, each thread is the background thread. Then just overhead of the program's main thread, the entire program is over. The sample code is as follows:
Using system;
Using system.threading;
Class myapp
{
Public static void main ()
{
For (int i = 0; i <10; i ) {
Thread thread = new thread (New Threadstart (threadfunc));
Thread.isbackground = true;
Thread.start ();
}
}
Private static void threadfunc ()
{
DateTime start = datetime.now;
While (DateTime.Now - Start). Seconds <5)
;
}
}
Since the reception thread and the background thread have this difference, how do we know how to set a thread's ISBACKGROUND attribute? Here is some basic principles: For some threads running in the background, these threads do not have to run when the program ends, then these threads should be set to the background thread. For example, a program launches a large number of arithmetic threads, but once the program ends, the thread lost its meaning, then that thread should be a background thread. For some threads that serve the user interfaces are often set to the front desk thread, because even if the main thread of the program is over, the threads of the other user interfaces are likely to continue to display the relevant information, so they cannot be immediately terminated. Here I only give some principles, and the actual use often requires further careful consideration of the programmer.
Thread priority
Once a thread starts running, the thread scheduler can control the CPU time obtained. If a hosted application is running on a Windows machine, the thread scheduler is provided by Windows. On other platforms, the thread scheduler may be part of the operating system, and naturally it may be part of the .NET framework. However, we don't have to consider how the thread's scheduler is generated, we only need to know the priority of the thread we can make the thread different CPU time.
The priority of threads is controlled by Thread.Priority property, which contains: ThreadPriority.Highest, ThreadPriority.Abovenormal, ThreadPriority.Normal, ThreadPriority.Belownormal, and ThreadPriority.lowest. From their name, we can naturally know their priority, so there is not much introduction here.
The default priority of thread is ThreadPriority.Normal. In theory, threads with the same priority will obtain the same CPU time, but when actually executed, the thread blocking or improvement of the operating system in the message queue will result in a thread having the same priority. CPU time. However, this difference can still be ignored from the moment. You can change the priority of a thread by changing the following methods. Thread.priority = threadpriority.abovenormal;
Or:
Thread.Priority = threadpriority.belownormal;
With the first statement above, you can improve a thread's priority, then the thread will get more CPU time; you will reduce the priority of that thread by the second sentence, so it will be Assigned to a few CPU time than the original. You can change its priority before running in a thread or at any time during its running process. In theory, you can also set the priority of each thread, but a thread that is too high in priority will often affect the operation of other threads, and even affect the operation of other programs, so it is best not to set up threads at will. level.
Hanging thread and restart thread
The Thread class provides two ways to suspend the thread and restart threads, that is, thread.suspend can suspend a running thread, and thread.resume can make the thread continue to run. Unlike the Windows kernel, .NET framework is not a number of hanging number of threads, so no matter how long you hang up, as long as you call thread.resume once, you can restart the hanging thread.
The Thread class also provides a static Thread.Sleep method that allows a thread to automatically hang a certain time and then automatically restart. A thread can call the Thread.Sleep method inside itself, and can also call the Thread.Suspend method inside itself, but must call its thread.ResuMe method to start again. Is this very easy to think? The following example shows how to use thread.sleep method:
While (continuedrawing) {
DrawnextSlide ();
Thread.sleep (5000);
}
Termination thread
In the hosted code, you can terminate another thread in one thread by the following statement:
Thread.abort ();
Let's explain how the Abort () method works. Because all managed threads are managed at the public language, they can throw an exception within each thread. The Abort () method throws a ThreadAbortException exception in the target thread to lead to the termination of the target thread. However, the abort () method is called, the target thread may not be terminated immediately. Because as long as the target thread is calling the unmanaged code and has not returned, the thread will not terminate immediately. If the target thread is invoking the unmanaged code and falls into a dead cycle, the target thread will not terminate. However, this situation is just some special cases, more cases are the target thread in the calling code, once the abort () is called, the thread is terminated immediately.
In practical applications, a thread terminates another thread, but it is often necessary to wait for that thread to completely terminate it can continue to run, so we should use its Join () method. The sample code is as follows:
Thread.abort (); // Requires Termination of another thread
Thread.join (); // Only the other thread is completely terminated, it continues to run
However, if another thread has not terminated (whose reason is as mentioned above), we need to set a time limit to the Join () method, the method is as follows: thread.join (5000); // Pause 5 seconds
In this way, after 5 seconds, the thread is forcibly running no matter whether the thread is completely terminated. The method also returns a Boolean value, if true, indicates that the thread has been completely terminated, and if it is false, it indicates that the time limit has been limited.
Clock thread
The Timer class in the .NET framework allows you to use the clock thread, which is included in the System.Threading namespace, its role is to call a thread after a certain time interval. Below I show you a specific example, which is time interval in 1 second, and outputs different strings in the console, the code is as follows:
Using system;
Using system.threading;
Class myapp
{
Private static bool ticknext = true;
Public static void main ()
{
Console.WriteLine ("Press Enter to Terminate ...");
TimerCallback Callback = New TimelCallback (Ticktock);
Timer Timer = New Timer (Callback, NULL, 1000, 1000);
Console.readline ();
}
Private static void Ticktock (Object State)
{
Console.writeline (Ticknext? "Tick": "TOCK");
Ticknext =! Ticknext;
}
}
From the above code, we know that the first function callback will only occur after 1000 milliseconds, and the future function callback occurs every 1000 milliseconds, which is the third parameter in the constructor of the Timer object. Determined. The program will continue to generate a new thread after 1000 millisecond time intervals, and only the user enters the carriage return to end running. However, it is worth noting that although we set the time interval to 1000 milliseconds, it is often not very accurate when actually running. Because the Windows operating system is not a real-time system, and the public language is not real-time, so because the thread scheduling is changed, the actual operation is often not accurate to milliseconds, but it is already for general applications. It's enough, so you don't have to be very demanding.
summary
This article describes some of the basic knowledge that needs to be mastered in multi-threaded programming under .NET. From an article we can know that it is greatly simplified before .NET, it has been greatly simplified, but its function is not weakened. With some of the above basic knowledge, the reader can try to write the multi-threaded program under the .NET. However, to write multi-threaded applications that have more powerful and bugs, readers need to master advanced multi-threaded programming technologies such as thread synchronization, thread pool. Readers may wish to refer to some operating systems or technical series in multi-threaded programming.