Search code examples
c#processcpuaffinity

Why I can't get the ProcessorAffinity of a thread?


I'm making a program for CPU usage statistics. I have a list of Processes, each one with its Process.Threads. For each thread, I want to know its current affinity to know which CPU Core it is binded to, but ProcessThread.ProcessAffinity can only be set... not read!

Why? Is there a way to get this information?

Moreover, can I get it without calling low-level Win32 functions but just .NET Standards?


Solution

  • After the hint by @oliver-rogier, I've managed to do it by using the function to Set the mask (imported from C++). As explained in the docs:

    Return value

    If the function succeeds, the return value is the thread's previous affinity mask.

    [DllImport(@"kernel32.dll", SetLastError = true)]
    static extern IntPtr SetThreadAffinityMask(IntPtr hThread, IntPtr dwThreadAffinityMask);
    
    
    public static IntPtr GetThreadAffinityMask(uint threadId)
    {
        Thread.BeginThreadAffinity();
    
        // get the handle
        IntPtr hThread = OpenThread(ThreadAccess.SET_INFORMATION | ThreadAccess.QUERY_INFORMATION, false, threadId);
        if (hThread == INVALID_HANDLE_VALUE)
        {
            var err = GetLastError();
            return IntPtr.Zero;
        }
    
        // there is no "get" for affinity mask, but the "set" function returns the mask before the operation
        // so first set a temp mask to obtain the current one
        IntPtr old = SetThreadAffinityMask(hThread, new IntPtr((int)Math.Pow(2, Environment.ProcessorCount)) - 1);
        if (old == IntPtr.Zero)
        {
            var err = GetLastError();
            return old;
        }
    
        // then restore the original value
        SetThreadAffinityMask(hThread, old);
    
        CloseHandle(hThread);
        Thread.EndThreadAffinity();
    
        return old;
    }