Getting Started with C # threading 00

Source: Internet
Author: User
Tags terminates thread class

Content preview:

    • Threading Primer (threading concept, creating threads)
    • Synchronization Basics (Synchronization nature, thread safety, thread break, thread state, synchronization context)
    • Using threads (background tasks, thread pools, read and write locks, asynchronous proxies, timers, local storage)
    • Advanced Topics (non-blocking threads, lifting and resuming)

Overview:

C # supports executing code in parallel through multithreading, where one thread is a standalone instance and can run concurrently with other threads.

The CLR and the operating system open a thread for a C # program (the main thread), which can be used as a starting point for creating multithreading, for example:

Class ThreadTest {static void Main () {Thread t = new Thread (Writey); T.start ();//Run Writey on the new Threadwhile (True ) Console.Write ("X"); Write ' x ' forever}static void Writey () {while (true) Console.Write ("Y");//write ' Y ' forever}}

The result of the operation will be:

Xxxxxxxxxxxxxxxxyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxyyyyyyyyyyyyyyyyyyyyyyyyyyyy Yyyyyyyyyyyyyyyyxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyxxxxxxxxxxxxxxxxx Xxxxxxxxxxxxxxxxxxxxxxx

The main thread creates a thread T , performs an operation that repeats the output Y, and the principal threads perform the operation of the duplicate output x.
The CLR assigns a separate line stacks to each thread, so the local variables are stored separately for each thread, and in the following example we define a function with a local variable and execute the function at the same time as the main function and the new line thread.

static void Main () {new Thread (Go). Start (); Call Go () on a new Threadgo (); Call Go () on the main thread}static void Go () {//Declare and use a local variable-' cycles ' for (int cycles = 0; cycle s < 5; cycles++) Console.Write ('? ');}

Execution Result:

??????????

A separate variable cycleis created in each thread's memory stack, so the output is 10?
If you are referencing the same object, the thread shares this data:

Press CTRL + C to copy the code<textarea></textarea>Press CTRL + C to copy the code

Because two threads call Go (), they share the done variable, so done is output only once:

Done

The static variable provides a different way to share variables in the thread, here is an example:

Class ThreadTest {static bool done,//static fields is shared between all threadsstatic void Main () {new Thread (Go). Start (); Go ();} static void Go () {if (!done) {done = true; Console.WriteLine ("Done"); }}}

Here the output is not very sure, it looks like to output two times done, in fact, it is impossible. Let's exchange the order of Go,

Class ThreadTest {static bool done,//static fields is shared between all threadsstatic void Main () {new Thread (Go). Start (); Go ();} static void Go () {if (!done) {Console.WriteLine ("Done"); done = True;}}}

Done is possible to output two times. Because when a thread evaluates an if expression and then executes Console.WriteLine ("Done"), another thread may have the opportunity to output do before the value of the Do change.
In fact, in C # you can use lock to achieve this goal:

Class ThreadSafe {static bool Done;static object locker = new Object (); static void Main () {new Thread (Go). Start (); Go ();} static void Go () {lock (locker) {if (!done) {Console.WriteLine ("Done"), done = True;}}}}

When two threads compete for a lock at the same time, a thread waits, or blocks, until the lock is empty. This is mainly to ensure that only one thread can enter the critical code area at the same time, "done" will only be output once.
The code is protected in such a way that the uncertainty from the multithreaded context is called thread safety.
Temporarily paused, or blocked, is the basic function of thread synchronization.
If a thread wants to pause, or hibernate for a period of time, it can be used:

Thread.Sleep (Timespan.fromseconds (30)); Block for 30 seconds

A thread can wait for another thread to end by calling join:

Thread t = new thread (Go); Suppose go is a static function. T.start (); Thread.Join (t); Blocked, only to the end of the thread T.

How Threads work:
Internally, multithreading is managed by the thread scheduler, which is the CLR's job to replace the operating system. The thread scheduler ensures that all active threads are properly allocated execution time, as well as threads that are waiting (these threads do not consume CPU time).
On a single-core machine, thread scheduling is done in a way that quickly switches the time slices between active threads. As in the first example, a thread that repeats output x or Y rotates to get a time slice. In Windows XP, a time slice is a few milliseconds, which is more than the CPU switching between threads can do more things, a thread switch is a few milliseconds.
On multicore machines, the implementation of multithreading is a combination of time slice rotation and concurrency, where different threads run concurrently on different CPUs, because the number of threads that the machine is running is much larger than the number of CPUs, so it also requires time slices to switch.
Threads cannot control when they are executed, completely controlled by the operating system's time slice switching mechanism.

Threads and processes:

There are always interviewers who like to compare threads with processes, but they're not a level thing at all. All threads within a single application are logically or belong to a process. Process: An operating system unit that runs the application. Threads are somewhat similar to processes, such as: for instances, processes and threads are typical execution mechanisms for time slice rotations. The key difference is that the processes are independent of each other, and the threads in the same application are shared heap memory, which is where the performance comes in: One thread can run in the background and the other thread can display the resulting data.

When should I use Multithreading:

    • An ordinary multithreaded task that runs time-consuming tasks in the background. The main thread keeps running, the work line Cheng Gan backstage. In the Windows Form program, if the main thread is occupied for a long time, the keyboard and mouse actions cannot be processed, and then the program becomes "unresponsive". Therefore, the time-consuming tasks need to be run in the background, so that the main thread can guarantee the response to user input.
    • Multithreading is particularly useful in non-UI programs, such as Windows Services, when waiting for a response from another machine (such as an application server, database server, client) to wait for the main thread to remain unblocked.
    • Another use of multithreading is that when there is a lot of computation in the function, the function is divided into multiple threads that can be executed faster on multicore machines (with Environment.processorcount to get the number of CPU cores).
    • A C # program can be multithreaded in two ways: by creating a thread on the display, or by using a. NET shows the ability to create threads (such as BackgroundWorker, thread pools, timers, remote servers, Webserivce or ASP.), and in these cases, only multithreading. A single-threaded Web server is definitely not working. In a stateless Web server, multithreading is fairly straightforward. The main problem is if the locking mechanism of the cached data is processed.

When should not use Multithreading:

Multithreading also has shortcomings, the biggest problem is to make the program become complex, multithreading itself is not complex, the complexity lies in the interaction between threads. Can make the development cycle longer, and more bugs. So you need to design the interaction between multiple threads as simple as possible, or do not use multithreading, unless you can guarantee the good.

Excessive switching and allocation of memory stacks between threads can also lead to CPU resource consumption, typically, when hard disk IO is large, only one or two of the programs performing the task in turn perform better, while performance of multiple performance tasks is not good at the same time. The producer/consumer model is discussed later.

To create and start a thread:

You can create a thread with the constructor of the thread class, pass a ThreadStart proxy as a parameter, point to the function that will be executed, and the following is the definition of this proxy:

public delegate void ThreadStart ();

Executing the start () function, the thread starts running, the thread returns after the function finishes, and the following is the C # syntax for creating ThreadStart:

Press CTRL + C to copy the code<textarea></textarea>Press CTRL + C to copy the code

The thread t executes the go function, and the main thread also calls go, and the result is:

Hello!hello!

You can also use C # syntax sugar: The compiler will automatically create a ThreadStart proxy.

static void Main () {Thread t = new Thread (Go);//No need to explicitly use Threadstartt.start (); ...} static void Go () {...}

There is also a simpler syntax for anonymous functions:

static void Main () {Thread t = new Thread (delegate () {Console.WriteLine ("hello!");}); T.start ();}

Pass parameters to ThreadStart: This form can only pass one parameter

public delegate void Parameterizedthreadstart (object obj);
Class ThreadTest {static void Main () {Thread t = new Thread (Go); T.start (true);//= = Go (True) go (false);} static void Go (object uppercase) {BOOL upper = (bool) uppercase; Console.WriteLine (upper? "Hello!": "hello!");}

Results:

Hello! Hello!

If you are using anonymous functions: You can pass multiple arguments, and you do not need type conversions.

static void Main () {Thread t = new Thread (delegate () {WRITETEXT ("Hello");}); T.start ();} static void WriteText (string text) {Console.WriteLine (text);}

Another way to pass a parameter is to pass an instance past, rather than pass a static function:

Class ThreadTest {bool upper;static void Main () {threadtest Instance1 = new ThreadTest (); instance1.upper = true; Thread t = new Thread (Instance1. Go); T.start (); ThreadTest Instance2 = new ThreadTest (); Instance2. Go (); Main thread–runs with Upper=false}void Go () {Console.WriteLine (upper? "Hello!": "hello!"); }

thread naming: threads have a name property that is useful when debugging.

Class Threadnaming {static void Main () {Thread.CurrentThread.Name = "main"; Thread worker = new Thread (Go); worker. Name = "worker"; worker. Start (); Go ();} static void Go () {Console.WriteLine ("Hello from" + Thread.CurrentThread.Name);}}

Output:

Hello from Mainhello from worker

foreground thread and background thread:

By default, threads are foreground threads, which means that any foreground thread is running and the program is running. The background thread also terminates immediately when all foreground threads are terminated.

Instead of changing the thread from foreground to background, the priority and state of the thread in the CPU scheduler will not change.


Worker. IsBackground = True;worker. Start ();}}

If the program executes without parameters, the worker thread defaults to the foreground thread and waits for the user to enter it on the ReadLine line. At the same time, the main thread exits, but the program continues to run because ReadLine is also the foreground thread. If a parameter is passed to the main function, the state of the worker thread is set to the background state, and the program exits almost immediately at the end of the main thread-finally readline. When a background thread terminates in this way, any code is no longer executed, and this code is not recommended, so it is best to wait for all background threads before the program exits, which can be done with a time-out (Thread.Join). If, for some reason, the worker thread does not end, it can also terminate the thread, in which case it is better to log the logs to analyze what is causing the situation.

A foreground thread that is discarded in Windows Form is potentially dangerous because the program continues to run when the main thread ends and exits. In the Windows Task Manager, it disappears in the Application tab, but it is still in the Process tab. Unless the user explicitly ends it.

The possibility of a common program exit failure is to forget the foreground thread.

priority of the thread: The thread's priority determines the execution time of the thread.

Enum ThreadPriority {Lowest, BelowNormal, Normal, AboveNormal, highest}

When a thread has a priority of highest, it does not mean that the thread will run in real time, and that the priority of the process should be high if it is to run in real time. When the priority of your process is high, the system will deadlock if the program enters a dead loop. This is the time to press the power button. So, use caution.

It is best to separate the real-time threads and UI from the two threads and set them to different priorities through remote or shared memory communication, which requires the p/invoking Win32 API (createfilemapping and MapViewOfFile) for shared memory.

exception handling for threads: Once a thread is started, any code blocks that create threads within the Try/catch/finally range are not related to try/catch/finally.

public static void Main () {try {new Thread (Go). Start ();} catch (Exception ex) {//We ' ll never get here! Console.WriteLine ("exception!");} static void Go () {throw null;}}

The Try/catch in the example above is basically useless, and the newly created thread may be an unhandled null reference exception, preferably in the code to be executed by the threads in the exception capture:

public static void Main () {new Thread (Go). Start ();} static void Go () {try {... throw null;//This exception'll get caught below ...} catch (Exception ex) {typically log the Exception, and/or signal another threadthat we ' ve come unstuck ...}

Starting with the. NET2.0, any unhandled exception on the thread will cause the entire program to hang, meaning never to ignore the exception, and add Try/catch to each potentially unusual code in the function that is being executed. This can be a bit of a hassle, so a lot of people handle this with global exception handling:

Using system;using system.threading;using system.windows.forms;static class Program {static void Main () { Application.ThreadException + = HandleError; Application.Run (New MainForm ());} static void HandleError (object sender, Threadexceptioneventargs e) {Log exception, then either exit the app or continue. .}}

The Application.ThreadException event is triggered when the code throws an exception, so it looks perfect-all exceptions can be caught, but exceptions on the worker thread may not catch, and the constructor of the form in the main function executes before the Windows message loop: NET provides a low-level event Catch Global exception: Appdomain.unhandledexception, which can catch all exceptions (UI and non-UI). While it provides a good way to catch all exceptions and log exception logs, there is no way to block program relationships or to block them. NET Exception dialog box

Getting Started with C # threading 00

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.