![]() CATEGORIES: BiologyChemistryConstructionCultureEcologyEconomyElectronicsFinanceGeographyHistoryInformaticsLawMathematicsMechanicsMedicineOtherPedagogyPhilosophyPhysicsPolicyPsychologySociologySportTourism |
Nbsp; I/O Request PrioritiesIn Chapter 26, “Thread Basics,” I showed how setting thread priorities affects how threads are sched- uled. However, threads also perform I/O requests to read and write data from various hardware devices. If a low-priority thread gets CPU time, it could easily queue hundreds or thousands of I/O requests in a very short time. Because I/O requests typically require time to process, it is possible that a low-priority thread could significantly affect the responsiveness of the system by suspending high-priority threads, which prevents them from getting their work done. Because of this, you can see a machine become less responsive when executing long-running low-priority services such as disk defragmenters, virus scanners, content indexers, and so on.13 Windows allows a thread to specify a priority when making I/O requests. For more details about I/O priorities, refer to the white paper at http://www.microsoft.com/whdc/driver/priorityio.mspx. Unfortunately, the FCL does not include this functionality yet; hopefully, it will be added in a future version. However, you can still take advantage of this feature by P/Invoking out to native Win32 func- tions. Here is the P/Invoke code.
internal static class ThreadIO { public static BackgroundProcessingDisposer BeginBackgroundProcessing( Boolean process = false) {
ChangeBackgroundProcessing(process, true); return new BackgroundProcessingDisposer(process); }
public static void EndBackgroundProcessing(Boolean process = false) { ChangeBackgroundProcessing(process, false); }
private static void ChangeBackgroundProcessing(Boolean process, Boolean start) { Boolean ok = process ? SetPriorityClass(GetCurrentWin32ProcessHandle(), start ? ProcessBackgroundMode.Start : ProcessBackgroundMode.End) : SetThreadPriority(GetCurrentWin32ThreadHandle(), start ? ThreadBackgroundgMode.Start : ThreadBackgroundgMode.End); if (!ok) throw new Win32Exception(); }
// This struct lets C#'s using statement end the background processing mode public struct BackgroundProcessingDisposer : IDisposable { private readonly Boolean m_process; public BackgroundProcessingDisposer(Boolean process) { m_process = process; } public void Dispose() { EndBackgroundProcessing(m_process); } }
13 The Windows SuperFetch feature takes advantage of low-priority I/O requests. // See Win32’s THREAD_MODE_BACKGROUND_BEGIN and THREAD_MODE_BACKGROUND_END private enum ThreadBackgroundgMode { Start = 0x10000, End = 0x20000 }
// See Win32’s PROCESS_MODE_BACKGROUND_BEGIN and PROCESS_MODE_BACKGROUND_END private enum ProcessBackgroundMode { Start = 0x100000, End = 0x200000 }
[DllImport("Kernel32", EntryPoint = "GetCurrentProcess", ExactSpelling = true)] private static extern SafeWaitHandle GetCurrentWin32ProcessHandle();
[DllImport("Kernel32", ExactSpelling = true, SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] private static extern Boolean SetPriorityClass( SafeWaitHandle hprocess, ProcessBackgroundMode mode);
[DllImport("Kernel32", EntryPoint = "GetCurrentThread", ExactSpelling = true)] private static extern SafeWaitHandle GetCurrentWin32ThreadHandle();
[DllImport("Kernel32", ExactSpelling = true, SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] private static extern Boolean SetThreadPriority( SafeWaitHandle hthread, ThreadBackgroundgMode mode);
// http://msdn.microsoft.com/enus/library/aa480216.aspx [DllImport("Kernel32", SetLastError = true, EntryPoint = "CancelSynchronousIo")] [return: MarshalAs(UnmanagedType.Bool)] private static extern Boolean CancelSynchronousIO(SafeWaitHandle hThread); }
And here is code showing how to use it.
public static void Main () { using (ThreadIO.BeginBackgroundProcessing()) { // Issue lowpriority I/O requests in here (eg: calls to ReadAsync/WriteAsync) } }
You tell Windows that you want your thread to issue low-priority I/O requests by calling Thread IO’s BeginBackgroundProcessing method. Note that this also lowers the CPU scheduling priority of the thread. You can return the thread to making normal-priority I/O requests (and normal CPU scheduling priority) by calling EndBackgroundProcessing or by calling Dispose on the value returned by BeginBackgroundProcessing (as shown in the preceding code via C#’s using state- ment). A thread can only affect its own background processing mode; Windows doesn’t allow a thread to change the background processing mode of another thread. If you want all threads in a process to make low-priority I/O requests and have low CPU schedul- ing, you can call BeginBackgroundProcessing, passing in true for the process parameter. A process can only affect its own background processing mode; Windows doesn’t allow a thread to change the background processing mode of another process.
C HA P T E R 2 9 Date: 2016-03-03; view: 955
|