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

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- InvalidComObjectException.cs
- NonParentingControl.cs
- XPathDocumentNavigator.cs
- OleDbFactory.cs
- SplitterEvent.cs
- XmlElementList.cs
- MetadataItemSerializer.cs
- TextSelectionHighlightLayer.cs
- EventManager.cs
- TdsParserHelperClasses.cs
- BlurEffect.cs
- safelink.cs
- ClientUrlResolverWrapper.cs
- NotifyParentPropertyAttribute.cs
- Rect3DConverter.cs
- ComponentEditorPage.cs
- ResourcesChangeInfo.cs
- ConfigurationConverterBase.cs
- NavigationEventArgs.cs
- NamespaceInfo.cs
- RowToParametersTransformer.cs
- Aggregates.cs
- MdbDataFileEditor.cs
- NamespaceInfo.cs
- ECDiffieHellmanCngPublicKey.cs
- ExpressionBinding.cs
- HTTPNotFoundHandler.cs
- TextSimpleMarkerProperties.cs
- ZipIOCentralDirectoryBlock.cs
- ComplexType.cs
- ThicknessAnimationBase.cs
- RadioButtonList.cs
- EmptyStringExpandableObjectConverter.cs
- SQLByte.cs
- SignatureDescription.cs
- XmlAttribute.cs
- BuildManager.cs
- Stroke2.cs
- CaseStatement.cs
- HtmlShim.cs
- DataGridComboBoxColumn.cs
- FormViewUpdateEventArgs.cs
- IpcClientManager.cs
- CrossSiteScriptingValidation.cs
- srgsitem.cs
- OpenFileDialog.cs
- TransactedBatchContext.cs
- UnsafeNativeMethods.cs
- UpdateTranslator.cs
- TreeNodeClickEventArgs.cs
- Help.cs
- MessagePropertyDescriptionCollection.cs
- CommonXSendMessage.cs
- XamlInt32CollectionSerializer.cs
- MULTI_QI.cs
- TextBoxView.cs
- InfoCardAsymmetricCrypto.cs
- IconConverter.cs
- DataBindingExpressionBuilder.cs
- _ConnectionGroup.cs
- SyntaxCheck.cs
- WebPartChrome.cs
- DeflateInput.cs
- DisplayNameAttribute.cs
- DbTransaction.cs
- ErrorReporting.cs
- AnnotationDocumentPaginator.cs
- AppDomainAttributes.cs
- CommandConverter.cs
- WindowsListBox.cs
- HtmlFormAdapter.cs
- TypeGeneratedEventArgs.cs
- LayoutUtils.cs
- CrossSiteScriptingValidation.cs
- BrowserTree.cs
- EntityReference.cs
- ChannelDispatcher.cs
- EdmTypeAttribute.cs
- MailWriter.cs
- TrimSurroundingWhitespaceAttribute.cs
- XmlSerializationWriter.cs
- SystemIPGlobalStatistics.cs
- ToolStripContentPanel.cs
- ArglessEventHandlerProxy.cs
- _SslStream.cs
- PathSegment.cs
- FlowDocumentPageViewerAutomationPeer.cs
- BufferedGraphics.cs
- BatchServiceHost.cs
- ToolStripContentPanel.cs
- OutputCacheProfileCollection.cs
- ColorBlend.cs
- CaseInsensitiveHashCodeProvider.cs
- XmlEnumAttribute.cs
- ArglessEventHandlerProxy.cs
- Constants.cs
- PermissionSet.cs
- Effect.cs
- SerTrace.cs
- ErrorEventArgs.cs