ich muss mir einen kleinen Editor basteln, der sowohl ein 3D Panel als auch viel GUI hat. Ich möchte hier nun gerne C# mit Windows Forms benutzen, weil ich damit ganz einfach schneller eine GUI erzeugen kann. Für die 3D Ausgabe selbst benutze ich SharpDX.
Nun möchte ich gerne QueryPerformanceCounter für das Timing im 3D Panel benutzen. Das bedeutet Thread-Affinität setzen, damit QueryPerformanceCounter immer auf dem selben Prozessor benutzt wird. Nun sind aber Managed Threads nicht das selbe wie OS Threads, und mein Wissen über Managed Code geht nicht soooo tief als das ich mit Sicherheit sagen könnte, dass der foldende Code okay ist. Augenscheinlich funktioniert er, aber dass muss nicht viel heissen. Kann mal jemand der sich damit auskennt einen Blick drauf werfen? :) Bitte auch beachten, dass das Begin-EndThreadAffinity-Paar die MainLoop des Programms einschließt.
EDIT: Ich weiß zum Beispiel nicht, ober der Code zur Folge hätte, dass nun alle Managed Threads plötzlich auf demselben OS Thread laufen. Das wäre von Übel!
Code: Alles auswählen
static class NativeWin32
{
[DllImport("kernel32.dll")]
public static extern UIntPtr SetThreadAffinityMask(UIntPtr handle, UIntPtr mask);
[DllImport("kernel32.dll")]
public static extern bool GetProcessAffinityMask(IntPtr hProcess, out UIntPtr lpProcessAffinityMask, out UIntPtr lpSystemAffinityMask);
[DllImport("kernel32.dll")]
public static extern UIntPtr GetCurrentThread();
[DllImport("Kernel32.dll")]
public static extern bool QueryPerformanceCounter(out long lpPerformanceCount);
[DllImport("Kernel32.dll")]
public static extern bool QueryPerformanceFrequency(out long lpFrequency);
}
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
[SecurityPermission(SecurityAction.Demand, Flags=SecurityPermissionFlag.ControlThread)]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
// Ensure that the following code is always running on the current OS thread.
Thread.BeginThreadAffinity();
// Restrict the current OS thread to always run on the same processor.
UIntPtr proccessAffinityMaskPtr = (UIntPtr)0;
UIntPtr systemAffinityMaskPtr = (UIntPtr)0;
if (NativeWin32.GetProcessAffinityMask(Process.GetCurrentProcess().Handle, out proccessAffinityMaskPtr, out systemAffinityMaskPtr))
{
ulong proccessAffinityMask = proccessAffinityMaskPtr.ToUInt64();
if (proccessAffinityMask != 0)
{
proccessAffinityMask = (proccessAffinityMask & ((~proccessAffinityMask) + 1));
NativeWin32.SetThreadAffinityMask(NativeWin32.GetCurrentThread(), (UIntPtr)proccessAffinityMask);
}
}
// Create main form
MainForm mainForm = new MainForm();
mainForm.Show();
long qpcLastTime, qpcFrequency;
NativeWin32.QueryPerformanceFrequency(out qpcFrequency);
NativeWin32.QueryPerformanceCounter(out qpcLastTime);
// Main loop
while (mainForm.Created)
{
// Handle application events
Application.DoEvents();
// Test code to calculate elapsed seconds
long qpcCurrentTime;
NativeWin32.QueryPerformanceCounter(out qpcCurrentTime);
long elapsedTime = qpcCurrentTime - qpcLastTime;
if (elapsedTime < 0) elapsedTime = 0;
qpcLastTime = qpcCurrentTime;
double elapsedSeconds = (double)elapsedTime / (double)qpcFrequency;
// Render scene
mainForm.Render(elapsedSeconds);
}
// From here on code may run on any OS thread.
Thread.EndThreadAffinity();
}
}