ThreadPoolComponent:简化多线程
提供了一个围绕共享线程池的简单封装。可用于将任务分解为一组并发执行的线程。
引言
我很高兴地介绍我的 ThreadPoolComponent
,这是一个围绕共享 ThreadPool
的简单封装。可用于将任务分解为一组并发执行的线程。
使用方法
- 通过编码或将组件放置在控件上创建组件实例。
- 处理
ThreadStarted
事件。当每个线程启动时,将调用事件处理程序,并应执行实际工作。 - 如果需要,可以选择处理
ThreadFinished
和AllThreadsFinished
事件以获得通知。 - 组件的默认行为是将每个线程绑定到单个 CPU 核心。调整
FirstAffinityIndex
属性以更改行为。 - 调用组件的
Start()
重载之一:Start()
:启动与可用 CPU 核心数量相同的线程Start(int numThreads)
:启动指定数量的线程Start(IEnumerable<T> tags)
:为每个指定状态对象启动一个线程(这些状态对象提供线程特定的输入和/或输出,它们作为ThreadStarted
和ThreadFinished
事件中使用的ThreadEventArgs
实例传递给线程)
这是相关示例程序的初始化代码:
var component = new ThreadPoolComponent();
component.ThreadStarted += new EventHandler<ThreadEventArgs>(component_ThreadStarted);
component.AllThreadsFinished += new EventHandler(component_AllThreadsFinished);
component.Start();
将组件放置在控件上进一步简化了此过程,因为您只需要双击事件即可创建处理程序。说到这里,这是示例实现:
void component_ThreadStarted(object sender, ThreadEventArgs e)
{
// if you supplied state objects when starting the threads,
// you may access the current thread's one using e.Tag
Console.WriteLine(string.Format("Thread #{0} says hello.", e.ThreadIndex));
}
void component_AllThreadsFinished(object sender, EventArgs e)
{
Console.WriteLine("---\nAll threads are finished.");
}
关注点
该组件使用共享 ThreadPool
,因为它通常通过回收线程来降低线程开销。组件尝试并发执行所有线程,因此线程的最大数量可能会增加。使用比 CPU 核心数量(由 static AvailableCpuCores
属性返回)更多的线程可能不是一个好主意。
通过设置其关联性将线程绑定到特定核心通常是有意义的,因为 CPU 核心通常具有单独的缓存。避免线程在核心之间跳转可以防止缓存被刷新,从而提高性能。不用担心,线程关联性在线程完成时会被重置,因此不会影响其他 ThreadPool
客户端。
请记住,ThreadPool
线程是后台线程,即如果所有前台线程退出,它们将不会使进程保持活动状态。
最后,您显然仍然需要在事件处理程序中同步对共享对象的访问。
历史
- 2009 年 3 月 9 日:初始发布