マネージドスレッドとオペレーティングシステムスレッドの分離は、.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
メソッドを使用してください(または、推奨されないメソッドを呼びたくない場合は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);
}
管理スレッドがOSスレッドにバインドされているという保証がないため、将来このコードが破損する可能性があります。しかし、私はこれを考えていません。