マネージド スレッドとオペレーティング システム スレッドの分離は .Net 2.0 にさかのぼり、SQL Server チームはファイバーを使用して .Net スレッドを実装する計画を立てています。これは実際にはどこにも行きませんでした。そのため、マネージド スレッドが常に同じオペレーティング システム スレッドで実行されるという保証はありませんが、実際には、これは現在のすべての .Net ホストに常に当てはまります。.Net 2.0 の導入以来、これが何年も変わっていないことを考えると、これが変わる可能性はほとんどありません。
この方法を使用することで、.Net の将来のバージョンに対しても自信を深めることができますSystem.Threading.Thread.BeginThreadAffinity
。これにより、マネージ スレッドが同じオペレーティング システム スレッド上にとどまることが保証されます (したがって、既定で既に true になっているため、既定の CLR ホストでは何もしません)。他のマネージド スレッドが同じオペレーティング システム スレッドを共有できる可能性はまだあると思いますが、これはありそうになく、現在の .Net ホストでは絶対にありません。
.Net は、クラスを使用してネイティブ オペレーティング システム スレッドにアクセスする機能を提供します。System.Diagnostics.ProcessThread
このクラスには、ProcessorAffinity
プロパティを使用してスレッドのプロセッサ アフィニティを変更する機能があります。ただし、特定のマネージド スレッドをそのスレッドにリンクすることProcessThread
は、意図的に難しくなっています。
それを行う唯一の実際の方法は、スレッド自体の内部からです。メソッドを使用します (または非推奨のメソッドを呼び出したくない場合は関数をSystem.AppDomain.GetCurrentThreadId
PInvoke しますが、Windows 以外のオペレーティング システムの Mono では機能しません)。GetCurrentThreadId
その後、これをプロパティに一致させることができ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 で機能しますが、理論的にはマネージド スレッドが OS スレッドにバインドされているという保証がないため、将来このコードが壊れる可能性があることに注意してください。しかし、私はこれが非常に可能性が低いと考えています。