ThreadPool.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ FXUpdate3074 / FXUpdate3074 / 1.1 / untmp / whidbey / QFE / ndp / clr / src / BCL / System / Threading / ThreadPool.cs / 4 / ThreadPool.cs

                            // ==++== 
//
//   Copyright (c) Microsoft Corporation.  All rights reserved.
//
// ==--== 
/*==============================================================================
** 
** Class: ThreadPool 
**
** 
** Purpose: Class for creating and managing a threadpool
**
**
=============================================================================*/ 

/* 
 * Below you'll notice two sets of APIs that are separated by the 
 * use of 'Unsafe' in their names.  The unsafe versions are called
 * that because they do not propagate the calling stack onto the 
 * worker thread.  This allows code to lose the calling stack and
 * thereby elevate its security privileges.  Note that this operation
 * is much akin to the combined ability to control security policy
 * and control security evidence.  With these privileges, a person 
 * can gain the right to load assemblies that are fully trusted which
 * then assertt full trust and can call any code they want regardless 
 * of the previous stack information. 
 */
 
namespace System.Threading {
    using System.Security;
    using System.Threading;
    using System.Runtime.Remoting; 
    using System.Security.Permissions;
    using System; 
    using Microsoft.Win32; 
    using System.Runtime.CompilerServices;
    using System.Runtime.ConstrainedExecution; 
    using System.Runtime.InteropServices;

    internal static class ThreadPoolGlobals
    { 
        //Per-appDomain quantum (in ms) for which the thread keeps processing
        //requests in the current domain. 
 
        public static uint tpQuantum = 2;
 
        public static int tpWarmupCount =  GetProcessorCount() * 2;

        public static bool tpHosted = ThreadPool.IsThreadPoolHosted();
 
        public static bool vmTpInitialized;
 
        public static ThreadPoolRequestQueue tpQueue = new ThreadPoolRequestQueue(); 

        [EnvironmentPermissionAttribute(SecurityAction.Assert, Read="NUMBER_OF_PROCESSORS")] 
        internal static int GetProcessorCount()
        {
            return Environment.ProcessorCount;
        } 
    }
 
    internal sealed class ThreadPoolRequestQueue 
    {
        private _ThreadPoolWaitCallback tpHead; 
        private _ThreadPoolWaitCallback tpTail;

        //The dummy object used to synchronize thread pool queue access.
        private Object tpSync; 

        //The number of work-items in thread pool queue. 
        private uint tpCount; 

        public ThreadPoolRequestQueue() 
        {
            tpSync = new Object();
        }
 
        public uint EnQueue(_ThreadPoolWaitCallback tpcallBack)
        { 
            uint count = 0; 
            bool tookLock = false;
            bool setNativeTpEvent = false; 

            RuntimeHelpers.PrepareConstrainedRegions();
            try
            { 
            }
            finally 
            { 
                RuntimeHelpers.PrepareConstrainedRegions();
                try 
                {
                    Monitor.Enter(tpSync);
                    tookLock = true;
                } 
                catch(Exception)
                { 
                } 

                if (tookLock) 
                {

                    if(tpCount == 0)
                    { 

                       //Indicate to the VM that there is work in this domain. 
                       //Its important to synchronize this notice, otherwise 
                       //the VM may not schedule any thread in this domain.
 
                       setNativeTpEvent = ThreadPool.SetAppDomainRequestActive();
                    }

                    tpCount++; 
                    count = tpCount;
 
                    if(tpHead == null) 
                    {
                        tpHead = tpcallBack; 
                        tpTail = tpcallBack;
                    }
                    else
                    { 
                        tpTail._next = tpcallBack;
                        tpTail = tpcallBack; 
                    } 

                    Monitor.Exit(tpSync); 

                    if(setNativeTpEvent)
                    {
                        ThreadPool.SetNativeTpEvent(); 
                    }
                } 
            } 

            return count; 
        }

        public _ThreadPoolWaitCallback DeQueue()
        { 
            bool tookLock = false;
            _ThreadPoolWaitCallback tpWaitCallBack = null; 
 
            RuntimeHelpers.PrepareConstrainedRegions();
            try 
            {
            }
            finally
            { 

                RuntimeHelpers.PrepareConstrainedRegions(); 
                try 
                {
                    Monitor.Enter(tpSync); 
                    tookLock = true;
                }
                catch(Exception)
                { 
                }
 
 
                if (tookLock)
                { 

                    _ThreadPoolWaitCallback head = tpHead;
                    if ( head != null)
                    { 
                        tpWaitCallBack = head;
                        tpHead = head._next; 
                        tpCount--; 

                        if(tpCount == 0) 
                        {
                            BCLDebug.Assert(tpHead == null,"TP Queue head expected to be null");

                            tpTail = null; 

                            //Indicate to the VM that there is no work in this 
                            //domain. Its important to synchronize this notice, 
                            //otherwise the VM may keep calling the Managed
                            //callbacks endlessly. 

                            ThreadPool.ClearAppDomainRequestActive();
                        }
                    } 

                    Monitor.Exit(tpSync); 
                } 
            }
 
            return tpWaitCallBack;
        }

        public uint GetQueueCount() 
        {
            return tpCount; 
        } 

 
    }


    internal sealed class RegisteredWaitHandleSafe : CriticalFinalizerObject 
    {
        private static readonly IntPtr InvalidHandle = Win32Native.INVALID_HANDLE_VALUE; 
        private IntPtr registeredWaitHandle; 
        private WaitHandle m_internalWaitObject;
        private bool bReleaseNeeded = false; 
        private int m_lock = 0;

        internal RegisteredWaitHandleSafe()
        { 
            registeredWaitHandle = InvalidHandle;
        } 
 
        internal IntPtr GetHandle()
        { 
           return registeredWaitHandle;
        }

        internal void SetHandle(IntPtr handle) 
        {
            registeredWaitHandle = handle; 
        } 

        [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] 
        internal void SetWaitObject(WaitHandle waitObject)
        {
            // needed for DangerousAddRef
            RuntimeHelpers.PrepareConstrainedRegions(); 
            try
            { 
            } 
            finally
            { 
                m_internalWaitObject = waitObject;
                if (waitObject != null)
                {
                    m_internalWaitObject.SafeWaitHandle.DangerousAddRef(ref bReleaseNeeded); 
                }
            } 
        } 

        [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] 
        internal bool Unregister(
             WaitHandle     waitObject          // object to be notified when all callbacks to delegates have completed
             )
        { 
            bool result = false;
            // needed for DangerousRelease 
            RuntimeHelpers.PrepareConstrainedRegions(); 
            try
            { 
            }
            finally
            {
                // lock(this) cannot be used reliably in Cer since thin lock could be 
                // promoted to syncblock and that is not a guaranteed operation
                bool bLockTaken = false; 
                do 
                {
                    if (Interlocked.CompareExchange(ref m_lock, 1, 0) == 0) 
                    {
                        bLockTaken = true;
                        try
                        { 
                            if (ValidHandle())
                            { 
                                result = UnregisterWaitNative(GetHandle(), waitObject == null ? null : waitObject.SafeWaitHandle); 
                                if (result == true)
                                { 
                                    if (bReleaseNeeded)
                                    {
                                        m_internalWaitObject.SafeWaitHandle.DangerousRelease();
                                        bReleaseNeeded = false; 
                                    }
                                    // if result not true don't release/suppress here so finalizer can make another attempt 
                                    SetHandle(InvalidHandle); 
                                    m_internalWaitObject = null;
                                    GC.SuppressFinalize(this); 
                                }
                            }
                        }
                        finally 
                        {
                            m_lock = 0; 
                        } 
                    }
                    Thread.SpinWait(1);     // yield to processor 
                }
                while (!bLockTaken);
            }
            return result; 
        }
 
        private bool ValidHandle() 
        {
            return (registeredWaitHandle != InvalidHandle && registeredWaitHandle != IntPtr.Zero); 
        }

        ~RegisteredWaitHandleSafe()
        { 
            // if the app has already unregistered the wait, there is nothing to cleanup
            // we can detect this by checking the handle. Normally, there is no race here 
            // so no need to protect reading of handle. However, if this object gets 
            // resurrected and then someone does an unregister, it would introduce a race
 
            // PrepareConstrainedRegions call not needed since finalizer already in Cer

            // lock(this) cannot be used reliably even in Cer since thin lock could be
            // promoted to syncblock and that is not a guaranteed operation 

            bool bLockTaken = false; 
            do 
            {
                if (Interlocked.CompareExchange(ref m_lock, 1, 0) == 0) 
                {
                    bLockTaken = true;
                    try
                    { 
                        if (ValidHandle())
                        { 
                            WaitHandleCleanupNative(registeredWaitHandle); 
                            if (bReleaseNeeded)
                            { 
                                m_internalWaitObject.SafeWaitHandle.DangerousRelease();
                                bReleaseNeeded = false;
                            }
                            SetHandle(InvalidHandle); 
                            m_internalWaitObject = null;
                        } 
                    } 
                    finally
                    { 
                        m_lock = 0;
                    }
                }
                Thread.SpinWait(1);     // yield to processor 
            }
            while (!bLockTaken); 
        } 

        [MethodImplAttribute(MethodImplOptions.InternalCall)] 
        private static extern void WaitHandleCleanupNative(IntPtr handle);

        [MethodImplAttribute(MethodImplOptions.InternalCall)]
        private static extern bool UnregisterWaitNative(IntPtr handle, SafeHandle waitObject); 
    }
 
[System.Runtime.InteropServices.ComVisible(true)] 
    public sealed class RegisteredWaitHandle : MarshalByRefObject
    { 
        private RegisteredWaitHandleSafe internalRegisteredWait;

        internal RegisteredWaitHandle()
        { 
            internalRegisteredWait = new RegisteredWaitHandleSafe();
        } 
 
        internal void SetHandle(IntPtr handle)
        { 
           internalRegisteredWait.SetHandle(handle);
        }

        internal void SetWaitObject(WaitHandle waitObject) 
        {
           internalRegisteredWait.SetWaitObject(waitObject); 
        } 

 
[System.Runtime.InteropServices.ComVisible(true)]
        // This is the only public method on this class
        public bool Unregister(
             WaitHandle     waitObject          // object to be notified when all callbacks to delegates have completed 
             )
        { 
            return internalRegisteredWait.Unregister(waitObject); 
        }
    } 

    [System.Runtime.InteropServices.ComVisible(true)]
    public delegate void WaitCallback(Object state);
 
    [System.Runtime.InteropServices.ComVisible(true)]
    public delegate void WaitOrTimerCallback(Object state, bool timedOut);  // signalled or timed out 
 
    internal class _ThreadPoolWaitCallback
    { 
        WaitCallback _waitCallback;
        ExecutionContext _executionContext;
        Object _state;
 
        //ThreadPoolWaitCallBack is the unit of thread pool work, and is
        //chained together. The _next field is the link. This field should be 
        //accessible to the Thread pool queue in order to reduce number of 
        //object allocations as this is on a perf-
 
        protected internal _ThreadPoolWaitCallback _next;

        static internal ContextCallback _ccb = new ContextCallback(WaitCallback_Context);
        static internal void WaitCallback_Context(Object state) 
        {
            _ThreadPoolWaitCallback obj = (_ThreadPoolWaitCallback)state; 
            obj._waitCallback(obj._state); 
        }
 

        internal _ThreadPoolWaitCallback(WaitCallback waitCallback, Object state, bool compressStack, ref StackCrawlMark stackMark)
        {
            _waitCallback = waitCallback; 
            _state = state;
            if (compressStack && !ExecutionContext.IsFlowSuppressed()) 
            { 
                // clone the exection context
                _executionContext = ExecutionContext.Capture(ref stackMark); 
                ExecutionContext.ClearSyncContext(_executionContext);
            }
        }
 
        // call back helper
        // This function dispatches requests to the user-callbacks. The 
        // work-items are fetched from the per-appdomain queue in a loop until 
        // either there is no more work or the quantum has expired. The quantum
        // is enforced to maintain fairness among appdomains. 

        static internal void PerformWaitCallback(Object state)
        {
            int totTime=0; 

            _ThreadPoolWaitCallback tpWaitCallBack = null; 
 
            int startTime = Environment.TickCount;
 
            do
            {
                tpWaitCallBack = ThreadPoolGlobals.tpQueue.DeQueue();
 
                if ( tpWaitCallBack == null)
                { 
                        break; 
                }
 
                // This call in the VM updates queue counts, number of
                // completed requests, etc. More importantly, it also
                // resets thread state like CriticalRegionCount, priority etc.
                // 

                ThreadPool.CompleteThreadPoolRequest(ThreadPoolGlobals.tpQueue.GetQueueCount()); 
 
                PerformWaitCallbackInternal(tpWaitCallBack);
 
                int endTime = Environment.TickCount;

                totTime = (endTime - startTime);
 
                // Check to see if quantum has expired.
 
                if(totTime > ThreadPoolGlobals.tpQuantum) 
                {
                    if(ThreadPool.ShouldReturnToVm()) 
                    {
                        break;
                    }
                } 

             } while (true); 
 
        }
 
        static internal void PerformWaitCallbackInternal(_ThreadPoolWaitCallback tpWaitCallBack)
        {

            // call directly if it is an unsafe call OR EC flow is suppressed 

            if (tpWaitCallBack._executionContext == null) 
            { 
                WaitCallback callback = tpWaitCallBack._waitCallback;
                callback(tpWaitCallBack._state); 
            }
            else
            {
                ExecutionContext.Run(tpWaitCallBack._executionContext, _ccb, tpWaitCallBack); 
            }
        } 
 
    };
 
    internal class _ThreadPoolWaitOrTimerCallback
    {
        WaitOrTimerCallback _waitOrTimerCallback;
        ExecutionContext _executionContext; 
        Object _state;
        static private ContextCallback _ccbt = new ContextCallback(WaitOrTimerCallback_Context_t); 
        static private ContextCallback _ccbf = new ContextCallback(WaitOrTimerCallback_Context_f); 

        internal _ThreadPoolWaitOrTimerCallback(WaitOrTimerCallback waitOrTimerCallback, Object state, bool compressStack, ref StackCrawlMark stackMark) 
        {
            _waitOrTimerCallback = waitOrTimerCallback;
            _state = state;
            if (compressStack && !ExecutionContext.IsFlowSuppressed()) 
            {
                // capture the exection context 
                _executionContext = ExecutionContext.Capture(ref stackMark); 
                ExecutionContext.ClearSyncContext(_executionContext);
            } 
        }
        static private void WaitOrTimerCallback_Context_t(Object state)
        {
            WaitOrTimerCallback_Context(state, true); 
        }
        static private void WaitOrTimerCallback_Context_f(Object state) 
        { 
            WaitOrTimerCallback_Context(state, false);
        } 

        static private void WaitOrTimerCallback_Context(Object state, bool timedOut)
        {
            _ThreadPoolWaitOrTimerCallback helper = (_ThreadPoolWaitOrTimerCallback)state; 
            helper._waitOrTimerCallback(helper._state, timedOut);
        } 
 

        // call back helper 
        static internal void PerformWaitOrTimerCallback(Object state, bool timedOut)
        {
            _ThreadPoolWaitOrTimerCallback helper = (_ThreadPoolWaitOrTimerCallback)state;
            BCLDebug.Assert(helper != null, "Null state passed to PerformWaitOrTimerCallback!"); 
            // call directly if it is an unsafe call OR EC flow is suppressed
            if (helper._executionContext == null) 
            { 
                WaitOrTimerCallback callback = helper._waitOrTimerCallback;
                callback(helper._state, timedOut); 
            }
            else
            {
                if (timedOut) 
                    ExecutionContext.Run(helper._executionContext.CreateCopy(), _ccbt, helper);
                else 
                    ExecutionContext.Run(helper._executionContext.CreateCopy(), _ccbf, helper); 
            }
        } 
    };

    [CLSCompliant(false)]
    [System.Runtime.InteropServices.ComVisible(true)] 
    unsafe public delegate void IOCompletionCallback(uint errorCode, // Error code
                                       uint numBytes, // No. of bytes transferred 
                                       NativeOverlapped* pOVERLAP // ptr to OVERLAP structure 
                                       );
 
    [HostProtection(Synchronization=true, ExternalThreading=true)]
    public static class ThreadPool
    {
 
        [SecurityPermissionAttribute(SecurityAction.Demand, ControlThread = true)]
        public static bool SetMaxThreads(int workerThreads, int completionPortThreads) 
        { 
            return SetMaxThreadsNative(workerThreads, completionPortThreads);
        } 

        public static void GetMaxThreads(out int workerThreads, out int completionPortThreads)
        {
            GetMaxThreadsNative(out workerThreads, out completionPortThreads); 
        }
 
        [SecurityPermissionAttribute(SecurityAction.Demand, ControlThread = true)] 
        public static bool SetMinThreads(int workerThreads, int completionPortThreads)
        { 
            // We only alert the unmanaged thread up for up to 'tpWarmupCount' work items
            // which is NumProcs * 2.   This means that if you set the MinThreads higher
            // than that we don't [....] up quickly.  To fix this we bump up tpWarmupCount
            // to be the max of the MinThreads and NumProcs * 2.  This is a tatical fix 
            // (meaning there are better, but more invasive fixes).
            ThreadPoolGlobals.tpWarmupCount = Math.Max(ThreadPoolGlobals.GetProcessorCount() * 2, workerThreads); 
            return SetMinThreadsNative(workerThreads, completionPortThreads); 
        }
 
        public static void GetMinThreads(out int workerThreads, out int completionPortThreads)
        {
            GetMinThreadsNative(out workerThreads, out completionPortThreads);
        } 

        public static void GetAvailableThreads(out int workerThreads, out int completionPortThreads) 
        { 
            GetAvailableThreadsNative(out workerThreads, out completionPortThreads);
        } 

        [CLSCompliant(false)]
        [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
        public static RegisteredWaitHandle RegisterWaitForSingleObject(  // throws RegisterWaitException 
             WaitHandle             waitObject,
             WaitOrTimerCallback    callBack, 
             Object                 state, 
             uint               millisecondsTimeOutInterval,
             bool               executeOnlyOnce    // 
             )
        {
            StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
            return RegisterWaitForSingleObject(waitObject,callBack,state,millisecondsTimeOutInterval,executeOnlyOnce,ref stackMark,true); 
        }
 
        [CLSCompliant(false), 
         SecurityPermissionAttribute( SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.ControlEvidence | SecurityPermissionFlag.ControlPolicy)]
        [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable 
        public static RegisteredWaitHandle UnsafeRegisterWaitForSingleObject(  // throws RegisterWaitException
             WaitHandle             waitObject,
             WaitOrTimerCallback    callBack,
             Object                 state, 
             uint               millisecondsTimeOutInterval,
             bool               executeOnlyOnce    // 
             ) 
        {
            StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; 
            return RegisterWaitForSingleObject(waitObject,callBack,state,millisecondsTimeOutInterval,executeOnlyOnce,ref stackMark,false);
        }

 
        private static RegisteredWaitHandle RegisterWaitForSingleObject(  // throws RegisterWaitException
             WaitHandle             waitObject, 
             WaitOrTimerCallback    callBack, 
             Object                 state,
             uint               millisecondsTimeOutInterval, 
             bool               executeOnlyOnce,   //
             ref StackCrawlMark stackMark,
             bool               compressStack
             ) 
        {
            if (RemotingServices.IsTransparentProxy(waitObject)) 
                throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_WaitOnTransparentProxy")); 
            RegisteredWaitHandle registeredWaitHandle = new RegisteredWaitHandle();
 
            if (callBack != null)
            {
                _ThreadPoolWaitOrTimerCallback callBackHelper = new _ThreadPoolWaitOrTimerCallback(callBack, state, compressStack, ref stackMark);
                state = (Object)callBackHelper; 
                // call SetWaitObject before native call so that waitObject won't be closed before threadpoolmgr registration
                // this could occur if callback were to fire before SetWaitObject does its addref 
                registeredWaitHandle.SetWaitObject(waitObject); 
                IntPtr nativeRegisteredWaitHandle = RegisterWaitForSingleObjectNative(waitObject,
                                                                               state, 
                                                                               millisecondsTimeOutInterval,
                                                                               executeOnlyOnce,
                                                                               registeredWaitHandle,
                                                                               ref stackMark, 
                                                                               compressStack);
                registeredWaitHandle.SetHandle(nativeRegisteredWaitHandle); 
            } 
            else
            { 
                throw new ArgumentNullException("WaitOrTimerCallback");
            }
            return registeredWaitHandle;
        } 

 
        [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable 
        public static RegisteredWaitHandle RegisterWaitForSingleObject(  // throws RegisterWaitException
             WaitHandle             waitObject, 
             WaitOrTimerCallback    callBack,
             Object                 state,
             int                    millisecondsTimeOutInterval,
             bool               executeOnlyOnce    // 
             )
        { 
            if (millisecondsTimeOutInterval < -1) 
                throw new ArgumentOutOfRangeException("millisecondsTimeOutInterval", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegOrNegative1"));
            StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; 
            return RegisterWaitForSingleObject(waitObject,callBack,state,(UInt32)millisecondsTimeOutInterval,executeOnlyOnce,ref stackMark,true);
        }

        [SecurityPermissionAttribute( SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.ControlEvidence | SecurityPermissionFlag.ControlPolicy)] 
        [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
        public static RegisteredWaitHandle UnsafeRegisterWaitForSingleObject(  // throws RegisterWaitException 
             WaitHandle             waitObject, 
             WaitOrTimerCallback    callBack,
             Object                 state, 
             int                    millisecondsTimeOutInterval,
             bool               executeOnlyOnce    //
             )
        { 
            if (millisecondsTimeOutInterval < -1)
                throw new ArgumentOutOfRangeException("millisecondsTimeOutInterval", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegOrNegative1")); 
            StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; 
            return RegisterWaitForSingleObject(waitObject,callBack,state,(UInt32)millisecondsTimeOutInterval,executeOnlyOnce,ref stackMark,false);
        } 

        [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
        public static RegisteredWaitHandle RegisterWaitForSingleObject(  // throws RegisterWaitException
            WaitHandle          waitObject, 
            WaitOrTimerCallback callBack,
            Object                  state, 
            long                    millisecondsTimeOutInterval, 
            bool                executeOnlyOnce    //
        ) 
        {
            if (millisecondsTimeOutInterval < -1)
                throw new ArgumentOutOfRangeException("millisecondsTimeOutInterval", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegOrNegative1"));
            StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; 
            return RegisterWaitForSingleObject(waitObject,callBack,state,(UInt32)millisecondsTimeOutInterval,executeOnlyOnce,ref stackMark,true);
        } 
 
        [SecurityPermissionAttribute( SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.ControlEvidence | SecurityPermissionFlag.ControlPolicy)]
        [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable 
        public static RegisteredWaitHandle UnsafeRegisterWaitForSingleObject(  // throws RegisterWaitException
            WaitHandle          waitObject,
            WaitOrTimerCallback callBack,
            Object                  state, 
            long                    millisecondsTimeOutInterval,
            bool                executeOnlyOnce    // 
        ) 
        {
            if (millisecondsTimeOutInterval < -1) 
                throw new ArgumentOutOfRangeException("millisecondsTimeOutInterval", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegOrNegative1"));
            StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
            return RegisterWaitForSingleObject(waitObject,callBack,state,(UInt32)millisecondsTimeOutInterval,executeOnlyOnce,ref stackMark,false);
        } 

        [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable 
        public static RegisteredWaitHandle RegisterWaitForSingleObject( 
                          WaitHandle            waitObject,
                          WaitOrTimerCallback   callBack, 
                          Object                state,
                          TimeSpan              timeout,
                          bool                  executeOnlyOnce
                          ) 
        {
            long tm = (long)timeout.TotalMilliseconds; 
            if (tm < -1) 
                throw new ArgumentOutOfRangeException("timeout", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegOrNegative1"));
            if (tm > (long) Int32.MaxValue) 
                throw new ArgumentOutOfRangeException("timeout", Environment.GetResourceString("ArgumentOutOfRange_LessEqualToIntegerMaxVal"));
            StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
            return RegisterWaitForSingleObject(waitObject,callBack,state,(UInt32)tm,executeOnlyOnce,ref stackMark,true);
        } 

        [SecurityPermissionAttribute( SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.ControlEvidence | SecurityPermissionFlag.ControlPolicy)] 
        [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable 
        public static RegisteredWaitHandle UnsafeRegisterWaitForSingleObject(
                          WaitHandle            waitObject, 
                          WaitOrTimerCallback   callBack,
                          Object                state,
                          TimeSpan              timeout,
                          bool                  executeOnlyOnce 
                          )
        { 
            long tm = (long)timeout.TotalMilliseconds; 
            if (tm < -1)
                throw new ArgumentOutOfRangeException("timeout", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegOrNegative1")); 
            if (tm > (long) Int32.MaxValue)
                throw new ArgumentOutOfRangeException("timeout", Environment.GetResourceString("ArgumentOutOfRange_LessEqualToIntegerMaxVal"));
            StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
            return RegisterWaitForSingleObject(waitObject,callBack,state,(UInt32)tm,executeOnlyOnce,ref stackMark,false); 
        }
 
        [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable 
        public static bool QueueUserWorkItem(
             WaitCallback           callBack,     // 
             Object                 state
             )
        {
            StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; 
            return QueueUserWorkItemHelper(callBack,state,ref stackMark,true);
        } 
 
        [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
        public static bool QueueUserWorkItem( 
             WaitCallback           callBack     //
             )
        {
            StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; 
            return QueueUserWorkItemHelper(callBack,null,ref stackMark,true);
        } 
 
        [SecurityPermissionAttribute( SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.ControlEvidence | SecurityPermissionFlag.ControlPolicy)]
        [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable 
        public static bool UnsafeQueueUserWorkItem(
             WaitCallback           callBack,     //
             Object                 state
             ) 
        {
            StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; 
            return QueueUserWorkItemHelper(callBack,state,ref stackMark,false); 
        }
 
        //ThreadPool has per-appdomain managed queue of work-items. The VM is
        //responsible for just scheduling threads into appdomains. After that
        //work-items are dispatched from the managed queue.
        private static bool QueueUserWorkItemHelper(WaitCallback callBack, Object state, ref StackCrawlMark stackMark, bool compressStack ) 
        {
            bool success =  true; 
 
            if (callBack != null)
            { 
                        //The thread pool maintains a per-appdomain managed work queue.
                //New thread pool entries are added in the managed queue.
                //The VM is responsible for the actual growing/shrinking of
                //threads. 

                _ThreadPoolWaitCallback tpcallBack = new _ThreadPoolWaitCallback(callBack, state, compressStack, ref stackMark); 
 
                if(!ThreadPoolGlobals.vmTpInitialized)
                { 
                    ThreadPool.InitializeVMTp();
                    ThreadPoolGlobals.vmTpInitialized = true;
                }
 
                uint queueCount;
 
                queueCount = ThreadPoolGlobals.tpQueue.EnQueue(tpcallBack); 

                //Make sure the unmanaged thread pool creates some threads 
                //before accepting requests in the managed queue.

                if( (ThreadPoolGlobals.tpHosted) || (queueCount < ThreadPoolGlobals.tpWarmupCount))
                { 
                    success = AdjustThreadsInPool(ThreadPoolGlobals.tpQueue.GetQueueCount());
                } 
                else 
                {
                    UpdateNativeTpCount(ThreadPoolGlobals.tpQueue.GetQueueCount()); 
                }

                return success;
 
            }
            else 
            { 
                throw new ArgumentNullException("WaitCallback");
            } 

        }

        [MethodImplAttribute(MethodImplOptions.InternalCall)] 
        private static extern bool AdjustThreadsInPool(uint QueueLength);
 
        [MethodImplAttribute(MethodImplOptions.InternalCall)] 
        private static extern void UpdateNativeTpCount(uint QueueLength);
 
        [MethodImplAttribute(MethodImplOptions.InternalCall)]
        unsafe private static extern bool PostQueuedCompletionStatus(NativeOverlapped* overlapped);

        [MethodImplAttribute(MethodImplOptions.InternalCall)] 
        private static extern void InitializeVMTp();
 
        [CLSCompliant(false)] 
        [SecurityPermissionAttribute( SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.ControlEvidence | SecurityPermissionFlag.ControlPolicy)]
        unsafe public static bool UnsafeQueueNativeOverlapped(NativeOverlapped* overlapped) 
        {
                return PostQueuedCompletionStatus(overlapped);
        }
 
      // Native methods:
 
        [MethodImplAttribute(MethodImplOptions.InternalCall)] 
        private static extern bool SetMinThreadsNative(int workerThreads, int completionPortThreads);
 
        [MethodImplAttribute(MethodImplOptions.InternalCall)]
        private static extern bool SetMaxThreadsNative(int workerThreads, int completionPortThreads);

        [MethodImplAttribute(MethodImplOptions.InternalCall)] 
        private static extern void GetMinThreadsNative(out int workerThreads, out int completionPortThreads);
 
        [MethodImplAttribute(MethodImplOptions.InternalCall)] 
        private static extern void GetMaxThreadsNative(out int workerThreads, out int completionPortThreads);
 
        [MethodImplAttribute(MethodImplOptions.InternalCall)]
        private static extern void GetAvailableThreadsNative(out int workerThreads, out int completionPortThreads);

        [MethodImplAttribute(MethodImplOptions.InternalCall)] 
        internal static extern void CompleteThreadPoolRequest(uint QueueLength);
 
        [MethodImplAttribute(MethodImplOptions.InternalCall)] 
        internal static extern bool ShouldReturnToVm();
 
        [MethodImplAttribute(MethodImplOptions.InternalCall)]
        [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
        internal static extern bool SetAppDomainRequestActive();
 
        [MethodImplAttribute(MethodImplOptions.InternalCall)]
        [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] 
        internal static extern void ClearAppDomainRequestActive(); 

        [MethodImplAttribute(MethodImplOptions.InternalCall)] 
        internal static extern bool IsThreadPoolHosted();

        [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
        [MethodImplAttribute(MethodImplOptions.InternalCall)] 
        internal static extern void SetNativeTpEvent();
 
        [MethodImplAttribute(MethodImplOptions.InternalCall)] 
        private static extern IntPtr RegisterWaitForSingleObjectNative(
             WaitHandle             waitHandle, 
             Object                 state,
             uint                   timeOutInterval,
             bool                   executeOnlyOnce,
             RegisteredWaitHandle   registeredWaitHandle, 
             ref StackCrawlMark     stackMark,
             bool                   compressStack 
             ); 

        [Obsolete("ThreadPool.BindHandle(IntPtr) has been deprecated.  Please use ThreadPool.BindHandle(SafeHandle) instead.", false)] 
        [SecurityPermissionAttribute( SecurityAction.Demand, Flags = SecurityPermissionFlag.UnmanagedCode)]
        public static bool BindHandle(
             IntPtr osHandle
             ) 
        {
            return BindIOCompletionCallbackNative(osHandle); 
        } 

        [SecurityPermissionAttribute( SecurityAction.Demand, Flags = SecurityPermissionFlag.UnmanagedCode)] 
        public static bool BindHandle(SafeHandle osHandle)
        {
            if (osHandle == null)
                throw new ArgumentNullException("osHandle"); 

            bool ret = false; 
            bool mustReleaseSafeHandle = false; 
            RuntimeHelpers.PrepareConstrainedRegions();
            try { 
                osHandle.DangerousAddRef(ref mustReleaseSafeHandle);
                ret = BindIOCompletionCallbackNative(osHandle.DangerousGetHandle());
            }
            finally { 
                if (mustReleaseSafeHandle)
                    osHandle.DangerousRelease(); 
            } 
            return ret;
        } 

        [MethodImplAttribute(MethodImplOptions.InternalCall)]
        [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
        private static extern bool BindIOCompletionCallbackNative(IntPtr fileHandle); 
    }
} 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.


                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK