Dry share: The beginning and creation of a detailed thread

Source: Internet
Author: User
Tags terminates

Read Catalogue

    • Code download
    • First, the creation and start of a thread
    • Second, pass the data to a thread
    • Third, named thread
    • Iv. foreground thread and background thread
    • Five, Thread priority
    • Vi. Exception Handling

Original address: C # multithreaded Tour (2)--Create and start threads

C # multithreaded Tour directory:

C # multithreaded Tour (1)--Introduction and basic concepts

C # multithreaded Tour (2)--Create and start threads

C # multithreaded Tour (3)--thread pool

C # multithreaded Tour (4)--Synchronization Essence

......

C # multithreaded Tour (2)--Create and start threads

Back to the top of the code download

Thread_ Blog Park _cnblogs_jackson0714.zip

code example for the first ~ third article:

Back to TopFirst, the creation and start of a thread

In the first article, threads are created using The constructor of the thread class, passing a threadstart Delegate to implement where the thread starts executing. Here is the definition of ThreadStart:

summary://     represents the method that executes on a system.threading.thread.[ ComVisible (true)]public delegate void ThreadStart ();

Call a start method, and then set it to start running. The thread will run until this method returns, and the thread ends.

Here is an example of creating a ThreadStart delegate using the extended C # syntax : 2.1_threadstart

1 class ThreadTest 2 {3     static void Main () 4     {5         thread t = new Thread (new ThreadStart (Go)); 6         T.start ();  7         Go (); 8         Console.readkey (); 9     }10     static void Go () one     {         Console.WriteLine ("Hello!");     }14}

In this example, thethread T executes go (), which basically calls the Go () method with the main line, and the result is a two-time close Hello.

A thread can be easily created by specifying a method group, which is then inferred from C # ThreadStart delegate: 2.2_thread

1 class Program 2 {3     static void Main (string[] args) 4     {5         thread t = new Thread (Go); 6         T.start (); 7         Go (); 8         Console.readkey (); 9     }10 one     static void Go ()     {         Console.WriteLine ("Go");     }15}

Another simpler way is to use lambda expressions or Anonymous methods:2.3_lambaexpression

static void Main (string[] args) {    thread t = new Thread (() =>console.writeline ("Go"));    T.start ();    Console.readkey ();}
Go back to the top second, pass the data to a thread 1. Using lambda to pass a data

The simplest way to pass a parameter to the target method of a thread is to execute a lambda expression that invokes a method and passes the desired argument to the method.

2.4_passingdatatoathread

static void Main (string[] args) {    thread t = new Thread (() = Print ("A"));    T.start ();    Console.readkey ();} static void Print (String message) {    Console.WriteLine (message);}
2. Passing Multiple parameters

In this way, you can pass any number of arguments to this method. You can even wrap the entire implementation in a multi-statement Lambda :

2.5_passingdatatoathread

New Thread (() =>{    Console.WriteLine ("a");    Console.WriteLine ("B");}). Start ();

You can also simply do the same with the anonymous method in C # 2.0:

New Thread (Delegate () {    Console.WriteLine ("a");    Console.WriteLine ("B");}). Start ();
3. Transfer parameters using Thread.Start

Another way is to pass a parameter to the Thread 's Start method:

2.6_passingdatatoathread_threadstart

static void Main (string[] args) {    thread t = new Thread (Print);    T.start ("A");    Console.readkey ();} static void Print (object messageobj) {    String message = (string) messageobj;//must be converted    Console.WriteLine ( message);}

This works because the constructor of Thread is overloaded and accepts any of the following two types of delegates:

summary://     represents the method that executes on a system.threading.thread.[ ComVisible (true)]public delegate void ThreadStart ();//summary://     represents the method that executes on a system.thr Eading. thread.////parameters://   obj://An     object this contains data for the thread procedure.[ ComVisible (false)]public delegate void Parameterizedthreadstart (object obj);

This Parameterizedthreadstart only allows to receive one parameter. And because its type is object, it usually needs to be converted.

4.Lambda expressions and capture variables

As you can see from the example above, a lambda type is most used to pass data to a thread. However, you must be very careful to accidentally modify the capture variable after starting the thread, because these variables are shared. For example, the following:

2.7_lbdaexpressionsandcapturedvariables

for (int i =0;i<10;i++) {    new Thread (() = Console.Write (i)). Start ();}

This output is indeterminate and the following is a typical case:

The problem here is that the variable i points to the same memory address when the for loop executes. Therefore, when each thread calls Console.Write , the value of I may change while the thread is running.

The solution is to use a temporary variable:

2.8_lambdaexpressionsandcapturedvariables_solution

for (int i = 0; i < ten; i++) {    int temp = i;    New Thread (() = Console.Write (temp)). Start ();}

The variable temp is in a different block of memory in each iteration of the loop. So each thread captures a different memory location, and there's no problem. We can explain the problem in the previous code:

2.9_passingdata_temporaryvariable

String text = "A"; Thread A = new Thread (() = Console.WriteLine (text)); text = "B"; Thread B = new Thread (() = Console.WriteLine (text)); A.start (); B.start ();

Because two lambda expressions capture the same value of text , B is printed two times.

Back to top three, named thread

Each thread has a Name property that you can use conveniently for debugging. When the thread displays the Threads Window and Debug loaction toolbar inside the Visual Statudio, the thread's Name Properties are particularly useful. You can only set the name of the thread once, and then try to change it to throw an exception message.

The static Thread.CurrentThread property represents the currently executing thread.

In the following example 2.10_namingthread, we set the name of the main thread:

static void Main (string[] args) {    Thread.CurrentThread.Name = "Main Thread";    Thread t = new thread (Go);    T.name = "Worker Thread";    T.start ();    Go ();    Console.readkey ();} static void Go () {    Console.WriteLine ("Go! The current thread is {0} ", Thread.CurrentThread.Name);}
Back to top four, foreground thread and background thread

By default, you show yourself that the thread you created is the foreground thread. The foreground thread keeps the application alive as long as any one of them is running, and the latter thread is not. Once all the foreground threads are complete, the application ends and any running background thread terminates immediately.

The status of a thread's foreground / background is not associated with its priority and the configured execution time.

You can use the thread's isbackgroud property to query or change the background state of a thread.

Here is an example: 2.11_prioritytest

static void Main (string[] args) {    thread t = new Thread (() = Console.readkey ());    if (args. Length > 0)//If the main method does not pass    in Parameters {        //set thread as background thread, wait for user input.        //Because the main thread is in T. Start () terminates after execution,        //So the background thread T terminates immediately after the main thread exits, and the application ends.        T.isbackground = true;    }    T.start ();}

If the parameter is passed in when the program calls, the thread created is the foreground thread, and then waits for the user to enter it.

Also, if the main thread exits, the application will not exit because the foreground thread T does not exit.

On the other hand, if the main method passes in a parameter, the created thread is set to the background thread. When the main thread exits, the application exits immediately.

When a process terminates in this manner, the finally statement block inside any background thread execution stack will be circumvented.

This is a problem if your thread uses a finally (or using) statement block to perform cleanup work such as freeing resources or deleting temporary files. To avoid this, you can display the wait for the background thread to exit the application.

There are two ways to achieve this:

    1. If you create this thread yourself, you can call the Join method on this thread .
    2. If you use a thread pool, you can use an event to wait for the thread to be processed.

In both cases, you need to specify a timeout, so you can end a thread that refuses to complete for some reason. This is your alternative exit strategy: At the end, you want your application to shut down without requiring the user to remove it from Task Manager.

If a user forces the end of a. NET process by using Task Manager , all threads terminate as if they were a background thread. This is the observed behavior, so it will vary depending on the version of the CLR and the operating system.

Foreground threads do not need to be treated this way, but you must be careful to avoid bugs that can cause threads to end . One of the usual reasons that the application does not exit correctly is that there is an active foreground thread that is still alive.

Back to top five, thread priority

The priority of a thread determines how much of the execution time it can get relative to other threads in the operating system, and the following is the level of thread precedence:

summary://     Specifies the scheduling priority of a system.threading.thread.[ Serializable][comvisible (True)]public enum threadpriority{    Lowest = 0,    belownormal = 1,    Normal = 2,    AboveNormal = 3,    Highest = 4,}

Thread priority is important when multithreading is active at the same time.

Note: When you increase the thread priority, you need to be very careful, which can cause problems for other threads to access the hungry state of the resource.

When you raise the priority of a thread, it does not perform real-time work because it is limited by the application's process precedence. In order to perform real-time work, you must also prioritize processes by using the system.diagnostices process class:

using (Process p = process.getcurrentprocess ()) {    p.priorityclass = Processpriorityclass.high;}

Processpriorityclass.high is actually the highest priority: real-time. Setting a process priority to a real-time state will cause other threads to get no CPU time slices. If your application unexpectedly enters an infinite loop state, you may even find that the operation is locked and only the power key can save you. For this reason,high is often the best choice for real-time applications.

If your real-time application has a user interface, increasing the priority of the program will make the refresh interface take up expensive CPU time and make the whole system run slowly (especially when the UI is complex). Reducing the primary thread priority and raising the priority of the process ensures that the real-time thread is not preempted by the interface redraw, but does not address the lack of CPU access to other processes , because the operating system will always allocate a disproportionate amount of resources to the process. An ideal solution is to allow real-time threads and user interfaces to run in different processes with different priorities, communicating through remote and memory mapped files. Even if the process priority is increased, there is a limit to how well the system needs to handle hard work in a managed environment. In addition, hidden problems will be introduced by automatic garbage collection, the operating system will encounter new challenges, even unmanaged code, the use of dedicated hardware or special real-time platform, it will be the best solution.

Back to top six, exception handling

The thread created within any try/catch/finally statement block scope is not associated with the statement block when the thread starts.

Consider the following procedure:

Reference Example: 2.12_exceptionhandling

static void Main (string[] args) {    try    {        new Thread (Go). Start ();    }    catch (Exception ex)    {        Console.WriteLine ("Exception");    }    Console.readkey ();} static void Go () {    throw null;}

The Try/catch declaration is invalid in this example, and the newly created thread will be blocked by an unhandled NullReferenceException . This behavior is good when you consider that each thread has a separate execution path.

The improved method is to move the exception handler to the Go () method:

Reference Example: 2.13_exceptionhandling_remedy

Class program{    static void Main (string[] args)    {        new Thread (Go). Start ();        Console.readkey ();    }    static void Go ()    {        Try        {            throw null;        }        catch (Exception ex)        {            Console.WriteLine (ex. Message);}}}    

You need to add a exception handler to all thread entry methods in your application , just as you did in the primary thread. An unhandled thread will cause the entire application to close and a bad window will pop up.

When writing this exception handling statement block, you may rarely overlook this problem, typically, you might log exception details, and then perhaps display a window that allows the user to automatically submit the information to your on the Web server. Then you may turn off the application - because this error destroys the state of the program. Then, the overhead is that the user may lose his recent work, such as open documents.

For WPF and WinForm applications, the global exception handling event ( Application.dispatcherunhandlerexception and application.threadexception) will only detect the main UI The exception that is thrown on the thread. You still have to handle the thread's exception manually.

AppDomain.CurrentDomain.UnhandledException can detect any unhandled exception, but cannot block the application from shutting down.

However, in some cases you do not need to handle exceptions on the thread because the . NET Framework has done this for you. Here's what's not mentioned:

Asynchronous delegates

Backgroudworker

The Task Parallel Library (conditions apply)

Dry share: The beginning and creation of a detailed thread

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.