在Microsoft.Net中设置线程处理器关联

在Microsoft.Net中设置线程处理器关联,.net,cpu,affinity,.net,Cpu,Affinity,(发布这篇文章并附上答案,因为我在任何地方都找不到关于如何做这件事的完整解释,所以我认为它可能对某些人有价值) 如何在Microsoft.Net中设置特定线程的处理器相关性?通过设置进程的关联性很简单,但该类不提供此类功能,.Net不保证托管线程链接到任何特定的操作系统线程。托管线程和操作系统线程之间的分离可以追溯到.Net 2.0,SQL Server团队计划使用光纤实现.Net线程。这从来没有真正实现过,因此虽然不能保证托管线程始终在同一操作系统线程上运行,但实际上,对于所有当前的.Net主

(发布这篇文章并附上答案,因为我在任何地方都找不到关于如何做这件事的完整解释,所以我认为它可能对某些人有价值)


如何在Microsoft.Net中设置特定线程的处理器相关性?通过设置进程的关联性很简单,但该类不提供此类功能,.Net不保证托管线程链接到任何特定的操作系统线程。

托管线程和操作系统线程之间的分离可以追溯到.Net 2.0,SQL Server团队计划使用光纤实现.Net线程。这从来没有真正实现过,因此虽然不能保证托管线程始终在同一操作系统线程上运行,但实际上,对于所有当前的.Net主机来说,情况总是如此。考虑到自.NET2.0推出以来,这种情况一直没有改变,因此这种情况不太可能改变

通过使用该方法,甚至可以增强我们对未来版本的.Net的信心。这保证了托管线程将保持在同一个操作系统线程上(因此它在默认CLR主机上不执行任何操作,因为默认情况下已经是这样)。我认为其他托管线程仍有可能共享同一操作系统线程,但这似乎不太可能,而且在当前的.Net主机中肯定不是这样

.Net提供了使用该类访问本机操作系统线程的能力,该类还可以使用该属性更改线程的处理器关联性。然而,将一个特定的托管线程链接到它的
ProcessThread
是故意造成的困难

唯一真正做到这一点的方法是从线程本身内部。使用该方法(如果您不想调用不推荐使用的方法,请使用PInvoke函数,尽管在Windows以外的操作系统上,该方法不适用于Mono)。然后可以将其与属性匹配

这使得使用以下代码(从线程内部调用)设置线程的处理器关联成为可能:

//
///设置当前线程的处理器相关性。
/// 
///CPU编号的列表。这些值应该是
///介于0和之间。
公共静态void SetThreadProcessorAffinity(参数int[]CPU)
{
如果(CPU==null)
抛出新的异常(“CPU”);
if(CPU.Length==0)
抛出新的ArgumentException(“您必须至少指定一个CPU。”,“CPU”);
//最多支持64个处理器
长cpuMask=0;
foreach(cpu中的int cpu)
{
如果(cpu<0 | | cpu>=Environment.ProcessorCount)
抛出新的ArgumentException(“无效的CPU号”);
cpuMask |=1L t.Id==osThreadId).Single();
//设置线程的处理器关联
thread.ProcessorAffinity=新的IntPtr(cpuMask);
}

记住,虽然在当前版本的.NET上工作,但理论上,缺少托管线程绑定到OS线程的保证可能会在将来破坏此代码。然而,我认为这不太可能。