c#ThreadPool 线程池的使用

一.设置线程池的最大最先线程数量

 ThreadPool.SetMaxThreads(16,16);// 设置线程池最大线程数量
 ThreadPool.SetMinThreads(8, 8);
 ThreadPool.GetMaxThreads(out workerThreads, out completionPortThreads);// 获取线程池最大线程数量
 ThreadPool.GetMinThreads(out workerThreads, out completionPortThreads);

二.简单使用线程池


// 将线程丢进线程池,参数是线程要做的事情            
ThreadPool.QueueUserWorkItem(t =>
{
      DoSomething("threadPool");
});

三.使用ManualResetEvent做到做到线程池的线程等待

ManualResetEvent manualResetEvent = new ManualResetEvent(false);// false代表线程会阻塞
ThreadPool.QueueUserWorkItem(t =>
{
     DoSomething("threadPool");
     // 等到这个线程完成这件事情后,就设置manualResetEvent变为true
     manualResetEvent.Set();// Set过后(manualResetEvent 变为true),WaitOne就会过去了
     // manualResetEvent.Reset();
});
manualResetEvent.WaitOne();// 只要没有Set回去,线程会一直卡在这里
// 一般来说不要阻塞线程池的线程,因为程序在运行过程中会出现一些问题(死锁问题)
// 如果非要使用那么一定要set回去

四.使用ManualResetEvent出现死锁的情况

            // 问题就是在k等于18的时候线程会死锁
            for (int i = 0; i < 20; i++)
            {
                int k = i;
                ThreadPool.QueueUserWorkItem(t =>
                {
                    Console.WriteLine(k);
                    if (k < 18)
                    {
                        // 因为我设置最大线程数只有16个,线程池里面的线程到达16个后就不会往后走了(此时线程都在使用中),就不会到达Set方法,所以就会死锁
                        manualResetEvent.WaitOne();// 等待
                    }
                    else
                    {
                        manualResetEvent.Set();// 恢复正常的代码
                    }
                });
            }
            if (manualResetEvent.WaitOne())
            {
                Console.WriteLine("没有死锁");
            }

            // 正常的执行是肯定先执行下面这一句
            Console.WriteLine("等着QueueUserWorkItem完成后才执行");

五.线程池回调(不带返回值)

        private void ThreadPoolWithCallback(Action act, Action callback) {
            ThreadPool.QueueUserWorkItem( t => {
                act.Invoke();
                Thread.Sleep(2000);
                callback.Invoke();
            });
        } 

// 使用的时候
 // 没有返回参数
            ThreadWithCallback(() =>
            {
                Console.WriteLine("这里是Action:" + Thread.CurrentThread.ManagedThreadId.ToString());
            }, () =>
            {
                Console.WriteLine("这里是CallBack:" + Thread.CurrentThread.ManagedThreadId.ToString());
            });

六.线程回调(带返回值)

private Func<T> ThreadWithReturn<T>(Func<T> func) {
            T t = default(T);
            Thread thread = new Thread(() =>
            {
                 t = func.Invoke();
            });
            thread.Start();

            // 返回一个委托函数
            // 委托函数里面还有一个return,这是属于另一个函数了
            // 在返回这个Func的时候是不会卡界面的
            return () =>
            {
                while (thread.ThreadState != ThreadState.Stopped)
                {
                    Console.WriteLine("我的");
                    Thread.Sleep(2000);
                }
                // 也可以
                //thread.Join();// 表示线程执行到这里后就等待
                return t;
            };
        }

// 使用的时候
 Func<int> func = ThreadWithReturn<int>(() => {
                Thread.Sleep(2000);
                return DateTime.Now.Millisecond;
            });

七.线程池的优点

1)降低资源消耗,尽最大可能的避免线程的创建和销毁带来的性能开销。

2)  提高响应速度,当任务来时可以直接使用,不用等待线程创建(在线程池的线程未被全部占用的时候,可以直接进行运算)

3)避免大量的线程间因互相抢占系统资源导致的阻塞现象。(线程池会自动管理线程)

4}提高线程的可管理性。(线程池会自动管理线程)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值