首页 > 代码库 > ThreadPool执行异步操作

ThreadPool执行异步操作


使用ThreadPool_类执行异步任务


/*
 ThreadPool 类是一个静态类型类,使用ThreadPool 类执行异步时通常调用ThreadPool 的 QueueUserWorkItem 方法,这个方法有一个重载版本,如下:

public static bool QueueUserWorkItem(WaitCallback callBack);
       
public static bool QueueUserWorkItem(WaitCallback callBack, object state);

QueueUserWorkItem 方法接受一个WaitCallback 类型的委托作为回调方法以及可以选择传递一个线程池线程执行回调方法时所需要的数据对象。

WaitCallback 委托类型的定义如下:

public delegate void WaitCallback(object state);

线程池的QueueUserWorkItem方法在调用以后会立即返回,所传递的回调方法会有以后线程池线程执行。使用线程池线程执行异步任务代码如下:
 
 
 */


示例如下:



namespace 使用ThreadPool_类执行异步任务
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("主线程开始执行任务,线程ID:{0}",Thread.CurrentThread .ManagedThreadId);
            //使用ThreadPool.QueueUserWorkItem方法将一个异步任务添加到线程池任务队列中,
            //可以为线程池线程执行方法时传递一个数据对象
            //如果不需要传递数据uk恶意使用QueueUserWorkerItem只有WaitCallback一个参数类型的版本
            //或传递null
            ThreadPool.QueueUserWorkItem(state => {

                Console.WriteLine("线程池线程开始执行异步任务。线程ID:{0}",Thread.CurrentThread .ManagedThreadId );
                for (int i = 0; i < 10; i++)
                {
                    Console.WriteLine(i);

                }
            
            },null );

            Console.WriteLine("主线程执行其他任务。线程ID:{0}",Thread .CurrentThread .ManagedThreadId );

            //使调用线程睡眠2000毫秒,等待线程池执行完成
            Thread.Sleep(2000);
            Console.WriteLine("主线程继续执行任务。线程ID:{0}",Thread.CurrentThread .ManagedThreadId);

        }
    }
}


技术分享





线程池对线程的管理



/*
 CLR允许开发人员设置线程池需要创建的最大和最小工作者线程和IO线程,但是最好不要设置线程池的线程数,CLR对线程池的工作者线程和I/O线程的最大线程数设置了1000的默认值。我们可以使用线程池的如下方法对线程池数进行设置和获得最大线程池数和当前运行线程数之间的差值
 * 
 * //设置可以同时处于活动状态的线程池的请求数目。
// 所有大于此数目的请求将保持排队状态,直到线程池线程变为可用。
public static bool SetMaxThreads(int workerThreads, int completionPortThreads);
 // 发出新的请求时,在切换到管理线程创建和销毁的算法之前设置线程池按需创建的线程的最小数量。   
public static bool SetMinThreads(int workerThreads, int completionPortThreads);
 //检索可以同时处于活动状态的线程池请求的数目。 所有大于此数目的请求将保持排队状态,直到线程池线程变为可用。
 public static void GetMaxThreads(out int workerThreads, out int completionPortThreads);
//发出新的请求时,在切换到管理线程创建和销毁的算法之前检索线程池按需创建的线程的最小数量。
 public static void GetMinThreads(out int workerThreads, out int completionPortThreads);

 //获得最大线程池线程数和当前运行线程数之间的差值。
public static void GetAvailableThreads(out int workerThreads, out int completionPortThreads);
 
 
 */


示例代码:


namespace 线程池对线程的管理
{
    class Program
    {
        static void Main(string[] args)
        {
            int worker, io;

            //获得线程池默认的最大线程数目。
            ThreadPool.GetMaxThreads(out worker ,out io);

            Console.WriteLine("1,CLR线程池默认最大线程数据,工作者线程数:{0},IO线程数:{1}",worker ,io );

            //设置线程池最大线程数
            ThreadPool.SetMaxThreads(100,100);
            ThreadPool.QueueUserWorkItem(state => {

                Thread.Sleep(2000);
                Console.WriteLine("4,线程池线程开始执行异步任务。线程ID:{0},",Thread.CurrentThread .ManagedThreadId );

            
            });

            Console.WriteLine("2,自定义设置线程池默认最大线程数据后,工作者线程数:{0},IO线程数: {1}:",worker ,io );
            //获得最大线程池线程数和当前运行线程数之间的差值
            ThreadPool.GetAvailableThreads(out worker ,out io );
            Console.WriteLine("3,获得最大线程池线程数和当前运行线程数之间的差值,工作者线程: {0},IO线程: {1}",worker ,io );
            Console.ReadKey();



        }
    }
}








技术分享





/*
 
 线程池中的工作者线程是许多异步计算任务锁使用的线程,在线程池内部,工作者线程采用先入先出的算法将工作项从线程的全家队列中取出工作项并执行任务。在同一时刻可能有多个工作者线程从全局队列中取出工作项,因此所有工作者线程都会竞争一个线程同步锁,以保证两个或更多工作者线程不会在同一时刻取出工作项。
 * 
 * 
 * 线程池在创建工作者线程时,默认会创建ThreadPool.setminthreads方法锁设置的值。如果没有设置这个值,就会创建应用程序进程允许的使用的CUP数相同的工作者线程,这些工作这线程简史线程池任务的执行情况,得以动态的创建更多的或销毁空闲线程。
 * 
 
 */



线程执行上下文的流动





/*
 每个线程都有一个执行上下文,执行上下文包含了安全设置,宿主设置和逻辑调用上下文数据,CLR默认是把初始线程的执行上下文数据向辅助线程流动,初始线程在收集和复制执行上下文数据并传递到辅助线程时会带来性能的损失。如果不需要这些执行上下文数据可以使用system.threading.executioncontext类组织执行上下文数据的流转。
 * 常用方法::::::::::::
 * 
 *         //     指示当前是否取消了执行上下文的流动。
        public static bool IsFlowSuppressed();
        //     恢复执行上下文在异步线程之间的流动。
        public static void RestoreFlow();
       //取消执行上下文在异步线程之间的流动。
        public static AsyncFlowControl SuppressFlow();

 
 
 
 
 */
namespace 线程执行上下文的流动
{
    class Program
    {
        static void Main(string[] args)
        {
            //把对象存储在调用逻辑上下文中,并将该对象与指定名称相关联
            System.Runtime.Remoting.Messaging.CallContext.LogicalSetData("key","这是主线程的执行上下文数据");

            Console.WriteLine("主线程执行上下文数据:{0}",System.Runtime .Remoting .Messaging .CallContext .LogicalGetData ("key"));

            //阻止主线程执行上下文数据的传递
            ExecutionContext.SuppressFlow();  //取消执行上下文在异步线程直接的流动
            Console.WriteLine("调用suppressFlow方法以后上下文传递流转是否被阻止:{0}",ExecutionContext .IsFlowSuppressed ().ToString ());



            ThreadPool.QueueUserWorkItem(state => {

                Console.WriteLine("执行上下文数据被阻止传递:{0}",System .Runtime .Remoting .Messaging .CallContext .LogicalGetData ("key"));

            
            });  //这里是没有输出的

            //恢复主线程执行上下文数据的传递
            ExecutionContext.RestoreFlow();//回复执行上下文在异步线程上的流动
            Console.WriteLine("调用RestoreFlow方法以后上下文传递流转是否被阻止:{0}",ExecutionContext .IsFlowSuppressed ().ToString ());

            ThreadPool.QueueUserWorkItem(state => {

                Console.WriteLine("执行上下文数据没有被阻止传递:{0}",System.Runtime.Remoting .Messaging .CallContext .LogicalGetData ("key"));

            
            
            });//将方法排入队列以便执行

            Console.ReadKey();


        }
    }
}


技术分享



ThreadPool执行异步操作