65.9K
CodeProject 正在变化。 阅读更多。
Home

ThreadPoolComponent:简化多线程

starIconstarIconstarIconstarIconemptyStarIcon

4.00/5 (3投票s)

2009年3月9日

CPOL

2分钟阅读

viewsIcon

18063

downloadIcon

323

提供了一个围绕共享线程池的简单封装。可用于将任务分解为一组并发执行的线程。

引言

我很高兴地介绍我的 ThreadPoolComponent,这是一个围绕共享 ThreadPool 的简单封装。可用于将任务分解为一组并发执行的线程。

使用方法  

  • 通过编码或将组件放置在控件上创建组件实例。
  • 处理 ThreadStarted 事件。当每个线程启动时,将调用事件处理程序,并应执行实际工作。
  • 如果需要,可以选择处理 ThreadFinishedAllThreadsFinished 事件以获得通知。
  • 组件的默认行为是将每个线程绑定到单个 CPU 核心。调整 FirstAffinityIndex 属性以更改行为。
  • 调用组件的 Start() 重载之一:
    • Start():启动与可用 CPU 核心数量相同的线程
    • Start(int numThreads):启动指定数量的线程
    • Start(IEnumerable<T> tags):为每个指定状态对象启动一个线程(这些状态对象提供线程特定的输入和/或输出,它们作为 ThreadStartedThreadFinished 事件中使用的 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 日:初始发布
ThreadPoolComponent:简化的多线程 - CodeProject - 代码之家
© . All rights reserved.