C # multithreaded programming Step 1-Understanding multithreading,

Source: Internet
Author: User

C # multithreaded programming Step 1-Understanding multithreading,

I. Concepts of process, thread and Multithreading

What is multithreading? I don't understand.

So what is thread? Speaking of threads, you have to talk about the process. I also searched for some materials on the Internet. Most of the processes mentioned are actually very abstract. In general, a process is an application that starts to run, so this application will have a process that belongs to this application.

The thread is the basic execution unit in the process. Each process has at least one thread, which is created based on the process. Therefore, this thread is called the main thread. Multi-threaded threads include other threads except the main thread. If a thread can execute a task, multiple threads can execute multiple tasks at the same time.

The above concepts are purely an individual's understanding. please correct me if anything is wrong.

 

Ii. Basic thread knowledge

Thread class

The Thread class is the basic class used to control threads. It exists in the System. Threading namespace. Thread can be used to control the creation, suspension, stop, and destruction of threads in the current application domain.

Some common attributes of Thread:

Common Thread methods:

Thread priority:

 

Iii. Simple Example of Multithreading

Let's start with simple multithreading. Here I have created a console application.

Class Program {static void Main (string [] args) {ThreadDemoClass demoClass = new ThreadDemoClass (); // create a new Thread thread Thread = new Thread (demoClass. run); // set it to the background thread. isBackground = true; // start thread. start (); Console. writeLine ("Main thread working... "); Console. writeLine ("Main thread ID is:" + Thread. currentThread. managedThreadId. toString (); Console. readKey () ;}} public class ThreadDemoClass {public void Run () {Console. writeLine ("Child thread working... "); Console. writeLine ("Child thread ID is:" + Thread. currentThread. managedThreadId. toString ());}}

Creating a New thread can also be usedThreadStartDelegation method. As follows:

// Create a delegate and pass the method to be executed as a parameter to the delegate ThreadStart threadStart = new ThreadStart (demoClass. Run); Thread thread = new Thread (threadStart );

Execution result:

Based on the above results, we can analyze and obtain that the main thread creates a subthread and starts it, but the main thread does not wait until the subthread completes execution, but continues to execute.

This involves thread Asynchronization or synchronization, which will be discussed later.

To continue with the above problem, if I want to continue the work of the main thread after the sub-thread execution is complete (of course, I don't think there is such a need ).

We can use the Join () method to modify the code:

Class Program {static void Main (string [] args) {ThreadDemoClass demoClass = new ThreadDemoClass (); // create a new Thread thread Thread = new Thread (demoClass. run); // set it to the background thread. isBackground = true; // start thread. start (); // wait until the thread completes thread. join (); Console. writeLine ("Main thread working... "); Console. writeLine ("Main thread ID is:" + Thread. currentThread. managedThreadId. toString (); Console. readKey () ;}} public class ThreadDemoClass {public void Run () {Console. writeLine ("Child thread working... "); Console. writeLine ("Child thread ID is:" + Thread. currentThread. managedThreadId. toString ());}}

Execution result:

The above Code adds a thread. Join (), which is used to block the subsequent threads until the current thread is completed. Of course, there are other ways to do this. For example, we can change thread. Join ()

The following code is used.

// Suspend the specified time of the current Thread. Sleep (100 );

In the current scenario, this can indeed meet the requirements, but there is a drawback in doing so: when the method logic executed by the sub-thread is complicated and takes a long time, this method is not always possible. Although the thread suspension time can be modified, the execution time is not fixed. Therefore, the Thread. Sleep () method is generally used to set the execution interval between multiple threads.

In addition, the Join () method also accepts a parameter used to specify the time when the thread is blocked. If the thread is not terminated within the specified time, false is returned, if it has been terminated within the specified time, true is returned.

 

The preceding multi-threaded method only outputs a piece of content. In most cases, we need to input parameters to the methods called by the thread and receive the returned values, however, the above method does not accept parameters and does not return values, so we can useParameterizedThreadStartThe delegate is used to create multiple threads. This delegate can accept an object-type parameter, which we can post on.

Class Program {static void Main (string [] args) {ThreadDemoClass demoClass = new ThreadDemoClass (); // create a delegate, and pass the method to be executed as a parameter to the delegate ParameterizedThreadStart threadStart = new ParameterizedThreadStart (demoClass. run); // create a new Thread thread Thread = new thread (threadStart); // start the Thread and input the thread parameter. start ("Brambling"); Console. writeLine ("Main thread working... "); Console. writeLine ("Main thread ID is:" + Thread. currentThread. managedThreadId. toString (); Console. readKey () ;}} public class ThreadDemoClass {public void Run (object obj) {string name = obj as string; Console. writeLine ("Child thread working... "); Console. writeLine ("My name is" + name); Console. writeLine ("Child thread ID is:" + Thread. currentThread. managedThreadId. toString ());}}

Execution result:

PS: I have not added this code here (thread. isBackground = true, that is, set the current thread to the background thread), because the thread is used. the Start () Start thread is the foreground thread by default. What is the difference between the foreground thread and the background thread?

The foreground thread means that the application domain will be automatically uninstalled only after all foreground threads have finished running. After it is set as a background thread, the application domain will be uninstalled when the main thread completes execution, rather than waiting for the asynchronous thread to complete execution.

The above result shows that the parameter is passed in multiple threads, but it only has one parameter. However, it accepts parameters of the object type (the source of ten categories), that is, it can be either a value type, a reference type, or a custom type. (Of course, the custom type actually belongs to the reference type) we use the custom type as the parameter to pass.

Class Program {static void Main (string [] args) {ThreadDemoClass demoClass = new ThreadDemoClass (); // create a delegate, and pass the method to be executed as a parameter to the delegate ParameterizedThreadStart threadStart = new ParameterizedThreadStart (demoClass. run); // create a new Thread thread Thread = new Thread (threadStart); UserInfo userInfo = new UserInfo (); userInfo. name = "Brambling"; userInfo. age = 333; // start the thread and input the thread parameter. start (userInfo); Console. writeLine ("Main thread working... "); Console. writeLine ("Main thread ID is:" + Thread. currentThread. managedThreadId. toString (); Console. readKey () ;}} public class ThreadDemoClass {public void Run (object obj) {UserInfo userInfo = (UserInfo) obj; Console. writeLine ("Child thread working... "); Console. writeLine ("My name is" + userInfo. name); Console. writeLine ("I'm" + userInfo. age + "years old this year"); Console. writeLine ("Child thread ID is:" + Thread. currentThread. managedThreadId. toString () ;}} public class UserInfo {public string Name {get; set;} public int Age {get; set ;}}

Execution result:

If you use a custom type as a parameter, more parameters can be used theoretically.

 

4. Thread Pool

It is relatively simple to use ThreadStart and ParameterizedThreadStart to create a thread. However, because thread creation and destruction require a certain amount of overhead, excessive use of threads will result in a waste of memory resources and thus affect performance, in consideration of performance, the thread pool concept is introduced. The thread pool does not create a thread immediately during CLR initialization, but initializes a thread only when the application wants to create a thread to execute the task, the initialization thread is the same as other threads, but will not be destroyed after the thread completes the task, but will return to the thread pool in the suspended state. When an application sends a request to the ready-made pool again, the suspended thread in the thread pool activates the execution task again. This reduces the overhead of thread creation and destruction. The default thread created by the thread pool isBackground thread.

Class Program {static void Main (string [] args) {ThreadDemoClass demoClass = new ThreadDemoClass (); // set the number of Idle threads maintained by the thread pool when there is no request. // The first parameter is the number of auxiliary threads. // The second parameter is the number of asynchronous I/O threads. ThreadPool. setMinThreads (5, 5); // sets the number of threads in the active thread pool at the same time. All requests exceeding the number of requests will remain in the queue, until the thread pool becomes available // The first parameter is the number of auxiliary threads // The second parameter is the number of asynchronous I/O threads ThreadPool. setMaxThreads (100,100); // use the delegate to bind the method to be executed by the thread pool (No parameter) WaitCallback waitCallback1 = new WaitCallback (demoClass. run1); // queue methods and execute ThreadPool when the thread pool becomes available. queueUserWorkItem (waitCallback1); // use the delegate to bind the method (with parameters) WaitCallback waitCallback2 = new WaitCallback (demoClass. run1); // queue methods and execute ThreadPool when the thread pool becomes available. queueUserWorkItem (waitCallback2, "Brambling"); UserInfo userInfo = new UserInfo (); userInfo. name = "Brambling"; userInfo. age = 33; // use the delegate to bind the method to be executed by the thread pool (with parameters, custom type parameters) WaitCallback waitCallback3 = new WaitCallback (demoClass. run2); // queue methods and execute ThreadPool when the thread pool becomes available. queueUserWorkItem (waitCallback3, userInfo); Console. writeLine (); Console. writeLine ("Main thread working... "); Console. writeLine ("Main thread ID is:" + Thread. currentThread. managedThreadId. toString (); Console. readKey () ;}} public class ThreadDemoClass {public void Run1 (object obj) {string name = obj as string; Console. writeLine (); Console. writeLine ("Child thread working... "); Console. writeLine ("My name is" + name); Console. writeLine ("Child thread ID is:" + Thread. currentThread. managedThreadId. toString ();} public void Run2 (object obj) {UserInfo userInfo = (UserInfo) obj; Console. writeLine (); Console. writeLine ("Child thread working... "); Console. writeLine ("My name is" + userInfo. name); Console. writeLine ("I'm" + userInfo. age + "years old this year"); Console. writeLine ("Child thread ID is:" + Thread. currentThread. managedThreadId. toString () ;}} public class UserInfo {public string Name {get; set;} public int Age {get; set ;}}

Execution result:

The thread created using the thread pool can also choose to pass parameters or do not pass parameters, and the parameters can also be value type or reference type (including custom type ). What did the above results find? Yes, the thread ID of the method to be executed for the first time is 6, and the thread ID of the method to be executed for the last time is also 6. This indicates that when the thread pool is requested for the first time, a thread is established in the thread pool. After the thread pool is executed, it returns to the thread pool in the suspended state. During the last request, the thread is awakened to execute the task again. This makes it easy to understand.

I also found a problem here, that is, the output sequence is not necessarily the same during each running. (Not only the thread pool, but also the previous one) because I didn't set any thread priority (the thread pool cannot set the thread priority), it actually involves thread security issues, obviously, this is NOT thread-safe. Let me give you a description, just as if I had to go to dinner after class at school.

Thread security should not be mentioned, but should be left behind (including the thread synchronization problem mentioned above). This blog aims to understand multithreading. Because I don't understand it too deeply...

We have implemented instances with no parameters and multiple threads with parameters and custom parameters, but there is also a common problem that no return value is returned. When we use multiple threads for actual development, most of them will need to return values, so we can try using member variables.

   class Program    {        List<UserInfo> userInfoList = new List<UserInfo>();        static void Main(string[] args)        {            Program program = new Program();            ParameterizedThreadStart threadStart = new ParameterizedThreadStart(program.Run);            Thread thread = null;            UserInfo userInfo = null;            for (int i = 0; i < 3; i++)            {                userInfo = new UserInfo();                userInfo.Name = "Brambling" + i.ToString();                userInfo.Age = 33 + i;                thread = new Thread(threadStart);                thread.Start(userInfo);                thread.Join();            }            foreach (UserInfo user in program.userInfoList)            {                Console.WriteLine("My name is " + user.Name);                Console.WriteLine("I'm " + user.Age + " years old this year");                Console.WriteLine("Thread ID is:" + user.ThreadId);            }                        Console.ReadKey();        }        public void Run(object obj)        {            UserInfo userInfo = (UserInfo)obj;            userInfo.ThreadId = Thread.CurrentThread.ManagedThreadId;            userInfoList.Add(userInfo);        }    }

Execution result:

The above method can barely meet the requirements of the returned value, but it has great limitations, because here I am using a member variable, therefore, the method called by the thread must be in the same class.

Therefore, the following method is used to call the method asynchronously.

 

V. Delegation

The asynchronous call of a delegate has two important methods: BeginInvoke () and EndInvoke ()

 

Not complete...

Related Article

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.