.Net内置的ThreadPool类大大方便了多线程程序的开发,.Net程序员不用像Java程序员那样自己去写线程池或者找别人写好的线程池了。
不过ThreadPool也有用起来不方便的地方,因为ThreadPool是一个进程内的单一线程池,无法构建单一的线程池,由于所在的线程中可能有其他地方向ThreadPool中添加任务,因此ThreadPool没有提供一个“放进去的所有任务执行完毕”这样的功能。难道我们就没有办法了吗?
不用担心,其实非常简单,只要借助于计算机专业都要学习的一门主干课《操作系统》中PV操作、信号量的知识点,可以很轻松的解决。为每个放到ThreadPool中的任务关联一个信号量,每个任务执行完毕后执行信号量的Set操作,Queue任务的主线程维护一个每个任务管理信号量的列表,把所有任务都Queue到ThreadPool中以后,逐个调用信号量的Wait操作,这样如果这个信号量对应的任务还没有执行完毕,那么Wait操作就会等待,如果执行完毕则Wait操作就不会阻塞,这样当所有的信号量Wait都返回了,就说明放进去的所有任务就都执行完成了。
我封装了一个简单的ThreadPoolEx类如下:
public class ThreadPoolEx
{
private class WorkItemInfo
{
public AutoResetEvent AutoResetEvent { get; set; }
public WaitCallback WaitCallback { get; set; }
public object UserState { get; set; }
}
private List<AutoResetEvent> handlerStack = new List<AutoResetEvent>();
public void QueueWorkItem(WaitCallback callBack,object userstate)
{
WorkItemInfo info = new WorkItemInfo();
info.AutoResetEvent = new AutoResetEvent(false);
handlerStack.Add(info.AutoResetEvent);
info.WaitCallback = callBack;
info.UserState = userstate;
ThreadPool.QueueUserWorkItem((state) => {
WorkItemInfo workItemInfo = (WorkItemInfo)state;
try
{
workItemInfo.WaitCallback(workItemInfo.UserState);
}
finally
{
workItemInfo.AutoResetEvent.Set();
}
}, info);
}
public void WaitAllComplete()
{
foreach(AutoResetEvent handler in handlerStack)
{
handler.WaitOne();
}
}
}
{
private class WorkItemInfo
{
public AutoResetEvent AutoResetEvent { get; set; }
public WaitCallback WaitCallback { get; set; }
public object UserState { get; set; }
}
private List<AutoResetEvent> handlerStack = new List<AutoResetEvent>();
public void QueueWorkItem(WaitCallback callBack,object userstate)
{
WorkItemInfo info = new WorkItemInfo();
info.AutoResetEvent = new AutoResetEvent(false);
handlerStack.Add(info.AutoResetEvent);
info.WaitCallback = callBack;
info.UserState = userstate;
ThreadPool.QueueUserWorkItem((state) => {
WorkItemInfo workItemInfo = (WorkItemInfo)state;
try
{
workItemInfo.WaitCallback(workItemInfo.UserState);
}
finally
{
workItemInfo.AutoResetEvent.Set();
}
}, info);
}
public void WaitAllComplete()
{
foreach(AutoResetEvent handler in handlerStack)
{
handler.WaitOne();
}
}
}
所有任务Queue进去以后,调用WaitAllComplete方法,当WaitAllComplete方法返回以后就说明任务执行完毕了。
调用方法实例代码如下:
ThreadPoolEx tpe = new ThreadPoolEx();
for (int i = 100; i > 0; i--)
{
tpe.QueueWorkItem((state) =>
{
Console.WriteLine(state);
},i);
}
tpe.WaitAllComplete();
Console.WriteLine('执行完成!');
for (int i = 100; i > 0; i--)
{
tpe.QueueWorkItem((state) =>
{
Console.WriteLine(state);
},i);
}
tpe.WaitAllComplete();
Console.WriteLine('执行完成!');
《操作系统》是非常有用的,学好计算机专业课发展才能更好。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!