Thread Scheduling Priority in .NET and no idle priority thread
I have seen numerous .net application where a background thread is created for background tasks but at the same time thread scheduling priority is never set. By default, managed thread runs with normal relative priority so now if you have a thread doing some maintenance work, that thread has no reason to run with Normal relative priority or sometime even the thread sending occasional updates to UI will run with normal relative priority
However, managed thread doesn’t allow you to set the thread priority to true THREAD_PRIORITY_IDLE class.
If you have done Win32 development then you are used to calling ::CreateThread() with Suspended flag and ::SetThreadPriority() to start thread with some priority. The default behavior of ::CreateThread is to create a thread with Normal Priority(relative to process priority class) same as managed Thread.Start(), but you will have to pass CREATE_SUSPENDED flag first.
If you insert a breakpoint in kernel32!CreateThread, you will see that Thread.Start() will call into this Win32 API because this is the only way you can create a thread in Windows OS, even if you use CRT _beginthreadex. One important difference is you don’t have an option to specify thread CreationFlags in managed code.
visit msdn documentation http://msdn.microsoft.com/en-us/library/74169f59.aspx for more information on Managed and Unmanaged Threading.
Managed Thread doesn’t support THREAD_PRIORITY_IDLE but rather maps it to THREAD_PRIORITY_LOWEST and also it doesn’t support THREAD_PRIORITY_TIME_CRITICAL.
PAL documentation says that SetThreadPriority should set THREAD_PRIORITY_IDLE to the least-priority value the host operating system allows, as the common language runtime sets threads to THREAD_PRIORITY_IDLE then busy-waits with a Sleep(0) loop until the garbage collection thread has run, with the garbage collection thread at a priority greater than idle.
Another important aspect to managed runtime is when you write your own host, you can use fiber to map one os thread to multiple managed threads with your own scheduling algorithm since fiber is implemented in usermode. Jeffrey Richter’s book “Programming Applications for Microsoft Windows” has very good description on Fiber. Windows OS supports fiber mainly for portability since other operating systems don’t have the same threading model.
But, if you do need to map managed thread priority to supported thread priority in windows , you can use System.Diagnositcs.ProcessThread. System.Diagnostics.ThreadPriorityLevel maps one to one with thread priority class in Win32 API(windows server 2003/XP).
Windows Vista/7 and windows server 2008 introduced THREAD_MODE_BACKGROUND_BEGIN and THREAD_MODE_BACKGROUND_END see the msdn documentation http://msdn.microsoft.com/en-us/library/ms686277(VS.85).aspx
If you really want to have your application to do task in background with minimal impact to system resources, you should consider setting thread priority to THREAD_MODE_BACKGROUND_BEGIN on Windows 7/2008 through interop.
One important point is, most of the managed application don’t really need a thread with idle priority, you can meet your application’s performance objectives by manipulating the thread scheduling priority less or higher than default Normal relative priority as defined in System.Threading.ThreadPriority Enumeration
Tags: Architecture