【IT168技术文档】
首先要搞清楚的是,托管代码中的线程(Thread)并不是真的线程(OS Thread)。它只是逻辑上我们划定的线程。逻辑上的线程并不执行,实际执行的是物理线程或者叫OS线程。而通常来说,每一个逻辑线程都对应的关联于某一条物理线程,这种关系一直维系到该逻辑线程的生命周期结束。要设置线程的处理器依赖我们先要得到当前实际运行的物理OS Thread或者叫物理线程,这时候需要使用Windows API – GetCurrentThreadId 。
class KernalHelper
{
[DllImport("kernel32")]
public static extern int GetCurrentThreadId();
}
然后再通过当前的osThreadID找到对应的ProcessThread,并设定其ProcessorAffinity。
以下代码演示了如何在一台双核PC的资源管理器里划出正弦曲线:
private fields#region private fields
private static int rounds = 0;
private static int MAXROUND = 60;
private static long[] sins = new long[MAXROUND];
private static PerformanceCounter pc;
private static bool tag = false;
#endregion
static void Main(string[] args)
{
Thread WatchThread = new Thread(() => GenerateSin(1));
WatchThread.Start();
Console.WriteLine("Press any key to break");
Console.ReadKey();
WatchThread.Abort();
}
public static void GenerateSin(int num)
{
//对当前物理线程设置处理器依赖
int osThreadId = KernalHelper.GetCurrentThreadId();
foreach (ProcessThread pt in Process.GetCurrentProcess().Threads)
{
if (osThreadId == pt.Id)
{
pt.ProcessorAffinity = (IntPtr)num;
}
}
try
{
tag = true;
//获得处理器的使用率
pc = new PerformanceCounter("Processor", "% Processor Time", "_Total");
for (int a = 0; a < MAXROUND; a++)
{
//六十个点的,振幅为5000000周期为60的正弦序列
sins[a] = (long)(5000000 * Math.Sin(Math.PI * a / (double)MAXROUND * 2f)) + 5000000;
}
long t1, t2;
long TimeSlide;
while (tag)
{
t1 = pc.RawValue + sins[rounds % MAXROUND];
TimeSlide = Stopwatch.GetTimestamp() + Stopwatch.Frequency;
t2 = TimeSlide - Stopwatch.Frequency + sins[rounds % MAXROUND] * Stopwatch.Frequency / 10000000;
while (pc.RawValue < t1)
{
Thread.Sleep(10);
}
while (Stopwatch.GetTimestamp() < TimeSlide) ;
rounds++;
}
}
catch (Exception ex)
{
Console.Write(ex.Message);
}
finally
{
pc.Close();
}
}