.NET:轮询访问ThreadPool:
问:我目前正在使用 Microsoft .NET Framework ThreadPool,在使用过程中我遇到了一种情况,不知道该如何解决。我需要处理一个较大批次的已在队列中的工作项,在第一个批次开始处理后第二个批次(规模稍小)到达。最初,较大批次中的一些工作将被分配给 ThreadPool 中的所有工作线程。但是,当第二批到达后,我想平均分配,使每一批都得到同样的服务,而不是先到的批次得到所有线程。
当其中一批完成时,我希望无论哪一个仍需处理的批次,都能够获得所有工作线程的关注。我该如何在 ThreadPool 顶层对此类批处理功能进行分层呢?
答:在以前的专栏中,我曾介绍过如何在现有 .NET ThreadPool 的顶层对各种类型的功能进行分层。在 2004 年 10 月刊的《MSDN 杂志》中,我介绍了如何使 ThreadPool 支持等待排队的工作项(请参见“ThreadPoolWait 和 HandleLeakTracker”)。在 2004 年 11 月刊中,我介绍了如何添加对工作项优先级的支持(请参见“ThreadPoolPriority 和 MethodImplAttribute”)。在 2006 年 3 月刊中,我介绍了如何添加取消支持(请参见“可以取消的线程池”)。将来,我可以回顾 2009 年 1 月这一期,并提到我曾介绍过如何在 ThreadPool 中添加轮询调度支持。
您需要解决的问题首先是要了解 ThreadPool 分派工作的原理。在内部,它维护一个已被加入其队列的工作项队列。当池中的某个线程可以执行工作时,它会返回到此工作队列并提取下一个项目。此处理顺序并未记录在案,因此是非常不可靠的(因为它可能而且很可能会在未来版本中有所变更)。
现在它可以通过一种非常简单的方式来实现:先进先出 (FIFO) 队列。因此,要排队的第一个工作将成为被线程所选中的第一个工作。在您的批处理情况中,这意味着第一批中的所有工作在队列中都将排在第二批所有工作的前面。因此,第一批的所有工作都将在第二批的所有工作之前进行分派。对于某些情况这是合理且最佳的方法。而对于您的情况,还需要进行更多的控制。
从 ThreadPool 获得这种控制的最简单方法之一是将您自己的委托替换为用户真正需要执行的委托。例如,假设您想捕获已排队工作中抛出的所有未处理异常并针对每个异常引发一个事件。要执行此操作,您可以编写如图 1 所示的代码。然后,使用 ExceptionThreadPool.QueueUserWorkItem 而不是使用 ThreadPool.QueueUserWorkItem。此工作仍将由 ThreadPool 来执行,但池中的线程实际执行的是您排队的委托,而非用户提供的委托。接下来在调用您的委托时将会调用用户提供的委托,而且会捕获所有异常并引发目标事件。
图 1 填充 ThreadPool
public static class ExceptionThreadPool {
public static void QueueUserWorkItem(
WaitCallback callback, object state) {
ThreadPool.QueueUserWorkItem(delegate {
try { callback(state); }
catch (Exception exc) {
var handler = UnhandledException;
if (handler != null)
handler(null,
new UnhandledExceptionEventArgs(exc, false));
}
});
}
public static event
UnhandledExceptionEventHandler UnhandledException;
}
请注意,此方法虽然功能很强大,但却需要付出一定的代价:需要分配额外的委托、需要调用额外的委托等等。成本是否过高只能根据您和您所处的环境来确定,但与从头编写自己的线程池相比,这种分层通常更具成本效益。
相关视频
相关阅读 vs.netIDE报"以下文件中的行尾不一致,要将行尾标准化吗?"的解决ie6下面asp.net mvc3 部署应用程序.NET 3.5 安装错误的四个原因及解决方法支持无限制历史记录的Paint.NET 3.5.8 Final,你用了吗?.NET Framework环境安装错误怎么办?JVM和.NET CLR和哪个会被彻底击败在asp.net mvc中实现右键菜单和简单的分页教程VB.NET如何得到调用当前过程的方法名称和类名称
热门文章 没有查询到任何记录。
最新文章
什么是.NET中的TDD?ASP.NET AJAX入门简介
WebMatrix入门教程VC++2008中如何调用GetOpenFileName打开文件PlaySound函数在VC++6.0中如何播放音乐及声请问VC++回调函数怎么用
人气排行 嵌入式实时操作系统VxWorks入门教程ArrayList 与 string、string[] 的转换C#遍历整个文件夹及子目录的文件代码WebMatrix入门教程asp.net判断文件或文件夹是否存在c#判断数据NULL值的方法vc++6.0怎么写Windows简单窗口代码.net解决数据导出excel时的格式问题
查看所有0条评论>>