Managed Threads Are Different From Windows Threads
.NET Framework works with managed threads and they aren't the same than Windows threads. Therefore, it isn't a good idea to use Windows API thread management functions with managed threads.When you create tasks in .NET Framework 4, managed threads are going to support the potential parallelization of their work. However, there isn't a direct relationship between the number of tasks created and the managed threads that support their execution. I talked about the relationship between tasks and managed threads in my previous post "Task Are Not Threads in .NET 4 Beta 1". Its content is still valid for .NET Framework 4 Release Candidate.
You can also assign work to managed threads through the thread pool manager, i.e., the System.Threading.ThreadPool class. Besides, it is possible to create your own managed threads by creating instances of the System.Threading.Thread class.
Developers that are used to work with Windows threads usually try to help the scheduler to assign a thread to the most appropriate hardware thread, i.e., the most convenient logical core. This way, they make sure that each thread runs in a separate hardware thread. This technique is known as "thread affinity".
Managed threads don't support methods to assign the most appropriate hardware thread to try to force the scheduler to use a specific hardware thread to execute a managed thread. .NET Compact Framework for Xbox 360 offers the SetProcessorAffinity method to the Thread class to allow developers to select the ideal hardware thread for XNA Framework games that target Xbox 360. However, this method isn't available in .NET Framework.
The problem is that a single managed thread can use one or more Windows threads to support its execution. Therefore, there isn't a one-to-one relationship between managed threads and Windows threads. In fact, a managed thread could use a Windows fiber to support its execution instead of a Windows thread according to the decisions taken by the managed scheduler.
A managed thread offers access to its ManagedThreadId property. This value also appears in the Threads Window. For example, a managed thread created by the thread pool manager, named "ThreadPool thread" has a value of 11 for its ManagedThreadId property (see Figure 1).
This ManagedThreadId value is an identifier for managed threads and it doesn't represent an Id for the Windows thread that supports its execution. Therefore, it can't be used in Windows API thread management functions. For example, it doesn't make sense to call the SetThreadAffinityMask function with a ManagedThreadId as the handle to the thread whose affinity mask is to be set (hThread). This function has the following C++ syntax definition:
DWORD_PTR WINAPI SetThreadAffinityMask( __in HANDLE hThread, __in DWORD_PTR dwThreadAffinityMask );
It is possible to determine the Windows thread that is executing the code for a managed thread and to retrieve its handle. However, it still doesn't make sense to call the SetThreadAffinityMask function for this Windows thread, because the managed scheduler can continue the execution of a managed thread in another Windows thread.
If you work with tasks in .NET Framework 4 (Release Candidate) or managed threads, the managed scheduler is going to try to set the best affinity. If you believe that you really need to work with thread affinity in your algorithms, you will have to work with the Windows API or other threading libraries.