(发布这个答案,因为我无法找到如何在任何地方执行此操作的完整说明,所以我认为它可能对某人有一些价值)
如何设置Microsoft .Net中特定线程的处理器关联?通过System.Diagnostics.Process.ProcessorAffinity
设置进程的亲和性是微不足道的,但System.Threading.Thread
类不提供此类功能,.Net不保证托管线程链接到任何特定的操作系统线程。
答案 0 :(得分:30)
托管和操作系统线程之间的分离可以追溯到.Net 2.0,并由SQL Server团队计划使用光纤实现.Net线程。这从来没有真正去过任何地方,所以虽然不能保证托管线程总是在同一个操作系统线程上运行,但实际上所有当前的.Net主机都是如此。鉴于自.Net 2.0引入以来这一年没有发生变化,这种情况不太可能发生变化。
使用System.Threading.Thread.BeginThreadAffinity
方法,即使对于.Net的未来版本,也可以增强我们的信心。这可以保证托管线程将保留在同一操作系统线程上(因此它在默认CLR主机上不执行任何操作,因为默认情况下这已经是真的)。我认为其他托管线程仍然可以共享相同的操作系统线程,但这似乎不太可能,在任何当前的.Net主机中绝对不是这样。
.Net提供了使用System.Diagnostics.ProcessThread
类访问本机操作系统线程的能力,并且该类能够使用ProcessorAffinity
属性更改线程的处理器关联。但是,将特定托管线程与其ProcessThread
链接起来是故意困难的。
唯一真正的方法是从线程内部开始。如果您不想调用已弃用的方法,请使用System.AppDomain.GetCurrentThreadId
方法(或PInvoke GetCurrentThreadId
函数,但这不适用于Windows以外的操作系统上的Mono)。然后可以将其与ProcessThread.Id
属性匹配。
这使得可以使用以下代码设置线程的处理器关联(从线程内部调用):
/// <summary>
/// Sets the processor affinity of the current thread.
/// </summary>
/// <param name="cpus">A list of CPU numbers. The values should be
/// between 0 and <see cref="Environment.ProcessorCount"/>.</param>
public static void SetThreadProcessorAffinity(params int[] cpus)
{
if( cpus == null )
throw new ArgumentNullException("cpus");
if( cpus.Length == 0 )
throw new ArgumentException("You must specify at least one CPU.", "cpus");
// Supports up to 64 processors
long cpuMask = 0;
foreach( int cpu in cpus )
{
if( cpu < 0 || cpu >= Environment.ProcessorCount )
throw new ArgumentException("Invalid CPU number.");
cpuMask |= 1L << cpu;
}
// Ensure managed thread is linked to OS thread; does nothing on default host in current .Net versions
Thread.BeginThreadAffinity();
#pragma warning disable 618
// The call to BeginThreadAffinity guarantees stable results for GetCurrentThreadId,
// so we ignore the obsolete warning
int osThreadId = AppDomain.GetCurrentThreadId();
#pragma warning restore 618
// Find the ProcessThread for this thread.
ProcessThread thread = Process.GetCurrentProcess().Threads.Cast<ProcessThread>()
.Where(t => t.Id == osThreadId).Single();
// Set the thread's processor affinity
thread.ProcessorAffinity = new IntPtr(cpuMask);
}
请记住,虽然这适用于当前版本的.Net,但理论上缺乏对托管线程绑定到操作系统线程的保证,将来可能会破坏此代码。但是,我认为这不太可能。