Line Cheng ThreadPool class and worker thread-< second >

Source: Internet
Author: User

One, CLR thread pool

The best way to manage thread overhead:

    1. Create threads as little as possible and reuse threads (thread pool initialization without threads, program request thread to create threads);
    2. It is best not to destroy but suspend the thread to achieve the avoidance of performance loss (thread pool created by threads that completed the task to suspend state back into the thread pools, waiting for the next request);
    3. A technique that allows an application to perform work, similar to a queue (multiple application request thread pools, the thread pool will queue each application);
    4. If a thread hangs for a long time and does not work, it needs to be completely destroyed and freed (the thread pool automatically monitors the threads that are not working for a long time and automatically destroys them);
    5. If the thread is not enough, the thread can be created, and the user can customize the maximum number of threads created (the thread pool will not sit idle when the queue is too long and the threads constructor are not enough);

Microsoft has already thought for us, has implemented the thread pool for us.

The CLR thread pool does not create a thread as soon as the CLR initializes, but instead initializes a thread when the application wants to create a thread to run the task.

  The thread pool is initialized with no thread, and the thread constructor. Threads are initialized like other threads, but after the task is completed, the thread does not destroy itself, but instead returns to the thread pool in a suspended state. The suspended thread in the thread pool activates the execution of the task again until the application makes a request to the thread pool again.

This saves the performance loss of building threads, and allows multiple tasks to reuse the same thread over and over again, saving significant overhead during the lifetime of the application.

threads established through the CLR thread pool are always default to background threads, with priority progression of Threadpriority.normal.
Worker thread vs. I/O thread

The CLR thread pool is divided into worker threads (workerthreads) and I/O threads (completionportthreads):

    • Worker threads are primarily used to manage the operation of internal CLR objects and are typically used to compute dense tasks.
    • I/O (input/output) threads are primarily used to interact with external systems, such as input and output, and the CPU only needs to pass the parameters of the task to the device at the beginning of the task, and then start the hardware device. When the task is completed, the CPU receives a notification, generally a hardware interrupt signal, at which time the CPU continues to work on subsequent processing. In the process, the CPU does not have to fully participate in the processing process, if the running thread does not hand over the control of the CPU, then the thread can only be in a wait state, even if the operating system to the current CPU scheduling to other threads, the thread occupied by the space is still occupied, and there is no CPU processing this thread, There may be a problem with thread resource wasting. If this is a network service program, each network connection using a thread management, there may be a large number of threads are waiting for network traffic, as the network connection continues to increase, the waiting state of the thread will be very exhausted all memory resources. Consider using a thread pool to solve this problem.

The maximum value for the thread pool is typically 1000, 2000 by default. When this number of requests is greater than this, the queued state is maintained until the line constructor thread is available.

Worker threads that use the CLR thread pool generally have two ways:

    • Through the ThreadPool.QueueUserWorkItem () method;
    • Through entrustment;

It is important to note that thread constructor threads are called, whether through ThreadPool.QueueUserWorkItem () or delegates.

Iii. Common methods of ThreadPool class

The following two methods allow you to read and set the maximum number of threads in the CLR thread pool for worker threads and I/O threads.

    1. Threadpool.getmax (out in workerthreads,out int completionportthreads);
    2. Threadpool.setmax (int workerthreads,int completionportthreads);

If you want to test how many threads in the thread pool are being put into use, you can pass the threadpool.getavailablethreads (out in Workthreads,out int conoletionportthreads) method.

Method Description
GetAvailableThreads Number of idle threads remaining
GetMaxThreads The maximum number of threads available, all requests that are greater than this number remain queued until the thread pool threads become available
GetMinThreads Retrieves the number of idle threads that the thread pool maintains in the new request forecast.
QueueUserWorkItem The boot line constructor a thread (the way the queue is queued, such as when the thread pool is temporarily out of idle threads, queues up into the queue)
SetMaxThreads Set the maximum number of threads in the thread pool
SetMinThreads Set the minimum number of threads that the thread pool needs to keep
    Class program    {        static void Main (string[] args)        {            int i = 0;            int j = 0;            The front is the auxiliary (that is, the so-called worker) thread, followed by the I/O thread            threadpool.getmaxthreads (out I, out j);            Console.WriteLine (i.tostring () + "   " + j.tostring ());//            get idle thread by default, because no asynchronous thread is used now, empty            Threadpool.getavailablethreads (out I, out j);            Console.WriteLine (i.tostring () + "   " + j.tostring ());//The default is            Console.readkey ();        }    }
Iv. methods of invoking thread pool threads

  1. Starting worker threads through QueueUserWorkItem

There are two overloaded static methods in the ThreadPool thread pool that can start worker threads directly:

    • ThreadPool.QueueUserWorkItem (WaitCallback);
    • ThreadPool.QueueUserWorkItem (Waitcallback,object);

The parameters of the Async method are treated as null when the WaitCallback delegate is directed to a non-return value method with the object parameter, and ThreadPool.QueueUserWorkItem (WaitCallback) can be used to start the method in one step.

Let's try a thread that uses the QueueUserWorkItem boot line constructor. Note that because it is always present in the thread pool, you do not need new thread ().

    Class program    {        static void Main (string[] args)        {            //MAX number of worker threads, maximum number            of I/O threads Threadpool.setmaxthreads (+);               Start worker thread            ThreadPool.QueueUserWorkItem (new WaitCallback (Runworkerthread));            Console.readkey ();        }        static void Runworkerthread (object state)        {            Console.WriteLine ("Runworkerthread begins to work");            Console.WriteLine ("Worker thread started successfully!");        }    }

Output:

  

Using the second overloaded method ThreadPool.QueueUserWorkItem (Waitcallback,object) method, you can pass the object objects as parameters to the callback function.

    Class program    {        static void Main (string[] args)        {person            p = new person (1, "Liu Bei");            Start worker thread            ThreadPool.QueueUserWorkItem (new WaitCallback (Runworkerthread), p);            Console.readkey ();        }        static void Runworkerthread (Object obj)        {            thread.sleep ($);            Console.WriteLine ("Thread pool threads start!");            Person p = obj as person;            Console.WriteLine (p.name);        }    }    public class person    {public person        (int id,string name) {id = ID; name = name; public        int Id {get; set;}        public string Name {get; set;}    }

The output results are as follows:

  

It is convenient to start worker threads through Threadpool.queueuserwork, but the WaitCallback delegate must be a non-return value method with the object parameter. So the worker thread that this method starts is only suitable for cases with a single parameter and no return value.

So what if you want to pass multiple arguments and have a return value? It is only through the Commission.

  2. BeginInvoke and EndInvoke delegate asynchronous calling thread

The steps to invoke the delegate asynchronously are as follows:

    1. Establishes a delegate object that invokes the delegate method asynchronously through the IAsyncResult BeginInvoke (string name,asynccallback callback,object state). BeginInvoke method In addition to the last two parameters, the other parameters are corresponding to the method parameters.
    2. You can end an asynchronous operation and get the result of the delegate's run, using EndInvoke (iasyncresult--the object returned by the previous step BeginInvoke) method.
    Class program    {        //except for the last two parameters, the front is the        delegate string MyDelegate (String Name,int age) you can define;        static void Main (string[] args)        {            //Establish a delegate            mydelegate mydelegate = new MyDelegate (GetString);            asynchronous invocation of the delegate, in addition to the last two parameters, the preceding parameters can be passed in            IAsyncResult result = Mydelegate.begininvoke ("Liu Bei", (a), NULL, NULL); //iasynresult can also poll judgment, the function is not weak            Console.WriteLine ("Main thread continues to work!");            Call EndInvoke (IAsyncResult) to get the result of the run, once the EndInvoke is called, even if the result has not yet returned, the main thread also blocks waiting            //Note the way to get the return value of            string data = MyDelegate.EndInvoke (result);            Console.WriteLine (data);            Console.readkey ();        }        static string GetString (string name, int age)        {            Console.WriteLine ("I am not thread pool threads" + Thread.CurrentThread.IsThreadPoolThread);            Thread.Sleep (+);            return string. Format ("I am {0}, this year {1} years old!", name,age);}    }

The output is as follows:

  

One drawback of this approach is that you do not know when the asynchronous operation is finished and when to start calling EndInvoke, because once the EndInvoke main thread is in a blocking wait state.

  3. IAsyncResult polling

In order to overcome the above mentioned shortcomings, at this time can make good use of IAsyncResult to improve the main thread performance, IAsyncResult has the following members.

Public interface iasyncresult{object asyncstate {get;}  Gets a user-defined object that qualifies or contains information about an asynchronous operation. Wailhandle asyncwaithandle {get;}  Gets the WaitHandle that is used to wait for the asynchronous operation to complete.  BOOL completedsynchronously {get;}//Gets an indication of whether the asynchronous operation completed synchronously.        BOOL iscompleted {get;} Gets an indication whether the asynchronous operation has completed. }

Examples are as follows:

    Class program    {        delegate string MyDelegate (string Name,int age);        static void Main (string[] args)        {            MyDelegate mydelegate = new MyDelegate (GetString);            IAsyncResult result = Mydelegate.begininvoke ("Liu Bei", n, null, NULL);            Console.WriteLine ("Main thread continues to work!");            Compared to the previous example, just using one more iscompleted attribute to determine whether an asynchronous thread completed while           (! result. iscompleted)            {                thread.sleep (+);                          Console.WriteLine ("Async thread is not finished, the main thread is doing other things!");            }            String data = MyDelegate.EndInvoke (result);            Console.WriteLine (data);            Console.readkey ();        }        static string GetString (string name, int age)        {            thread.sleep ();            return string. Format ("I am {0}, this year {1} years old!", name,age);}    }

The output is as follows:

  

The above example, in addition to the IsCompleted attribute, you can also use AsyncWaitHandle the following 3 methods to achieve the same polling judgment effect:

    • WaitOne: Determines whether a single asynchronous thread is complete;
    • WaitAny: Determines whether the async thread has a specified number of completed;
    • WAITALL: Determine if all asynchronous threads have completed;

WaitOne:

  Compared to the previous example, the judging condition is replaced by the iscompleted attribute AsyncWaitHandle, which is just while  (!result. Asyncwaithandle.waitone (+)  {      Console.WriteLine ("Async thread is not finished, the main thread continues to work!") ");  }

WaitAny:

  Whether the specified number of  waithandle[] waithandlelist = new waithandle[] {result was completed. AsyncWaitHandle};  while (WaitHandle.WaitAny (waithandlelist, 0) > 0)  {      Console.WriteLine ("The number of async threads is not greater than, the main thread continues to do other things!");  }

WAITALL:

  waithandle[] waithandlelist = new waithandle[] {result. AsyncWaitHandle};  Whether all asynchronous threads complete while  (! WaitHandle.WaitAll (Waithandlelist, $))  {      Console.WriteLine ("Async thread Not all finished, the main thread continues to do other things!");  }

4. IAsyncResult callback function

Using polling to detect the state of an async method is cumbersome and affects the main thread, which is inefficient. Can the asynchronous thread complete the call to implement the defined handler function directly?

Yes, or a powerful IAsyncResult object.

Class Program {delegate string MyDelegate (string name, int age);            static void Main (string[] args) {//Establish a delegate mydelegate mydelegate = new MyDelegate (GetString); The second-to-last argument, the delegate is bound to the completion of the callback method IAsyncResult RESULT1 = Mydelegate.begininvoke ("Liu Bei", 23,new AsyncCallback (completed), null); The main thread can continue to work without waiting for Console.WriteLine ("I am the main thread, I do my work, no longer talk to you!")            ");            Thread.Sleep (5000);        Console.readkey ();            } static string GetString (string name, int age) {Thread.CurrentThread.Name = "asynchronous Thread";            Note that if it is not set to the foreground thread, then the main thread is finished and the program is uninstalled directly//thread.currentthread.isbackground = false;            Thread.Sleep (2000); return string.        Format ("I am {0}, this year {1} years old!", name, age); }//method for asynchronous thread to complete callback static voidcompleted(IAsyncResult result)            {//Get delegate object, call EndInvoke method to get run result AsyncResult _result = (AsyncResult) result; MyDelegate mydelegaate = (mydelegate) _result.            AsyncDelegate;            Gets the parameter string data = Mydelegaate.endinvoke (_result);            Console.WriteLine (data); The asynchronous thread finishes executing Console.WriteLine ("Asynchronous thread is done!")            "); Console.WriteLine ("Callback function" is also called by "+ Thread.CurrentThread.Name +"!)        "); }    }

The output is as follows:

  

Attention:

    1. The callback function is still executed in the worker thread, so that it does not affect the running of the main threads.
    2. Thread pool threads default to a background thread. However, if the main thread takes precedence over the worker threads, then the program is unloaded and the callback function is not necessarily executed. If you do not want to lose the action in the callback function, either Cheng the async line as a foreground thread, or make sure that the main thread is Cheng than the guide.

So far, BeginInvoke ("Liu Bei", "AsyncCallback", "New" (completed), null) and the last parameter is useless. So what's the last argument for? To pass the parameter:

Namespace Console ___ Learning Test {class Program {delegate string MyDelegate (string name, int age);            static void Main (string[] args) {person p = new person (2, "Guan Yu");            Establishment of entrustment mydelegate mydelegate = new MyDelegate (GetString); The last parameter of the function, originally used to pass the IAsyncResult RESULT1 = Mydelegate.begininvoke ("Liu Bei", The new AsyncCallback (completed),P); The main thread can continue to work without waiting for Console.WriteLine ("I am the main thread, I do my work, no longer talk to you!")            ");        Console.readkey ();            } static string GetString (string name, int age) {Thread.CurrentThread.Name = "asynchronous Thread";            Note that if it is not set to the foreground thread, then the main thread is finished and the program is uninstalled directly Thread.CurrentThread.IsBackground = false;            Thread.Sleep (2000); return string.        Format ("I am {0}, this year {1} years old!", name, age);             }//method for asynchronous thread to complete callback static void completed (IAsyncResult result) {//Get delegate object, call EndInvoke method to get run result            AsyncResult _result = (AsyncResult) result; MyDelegate mydelegaate = (mydelegate) _result.            AsyncDelegate;            Gets the parameter string data = Mydelegaate.endinvoke (_result); Console.WriteLine (data);Person P= result. AsyncState asPerson ;Console.WriteLine ("Passed the parameter is:" + p.name); The asynchronous thread finishes executing Console.WriteLine ("Asynchronous thread is done!")            "); Console.WriteLine ("Callback function" is also called by "+ Thread.CurrentThread.Name +"!)        ");            }} public class Person {public person (int ID, string name) {id = ID;        name = name;            } public int Id {get;        Set            } public string Name {get;        Set }    }}

The output is as follows:

  

Line Cheng ThreadPool class and worker thread-< second >

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.