一.设置线程池的最大最先线程数量
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}提高线程的可管理性。(线程池会自动管理线程)