/// <summary>
        /// Returns a string containing the list of active threads and their tasks.
        /// It is not recommended to invoke this method very often.
        /// </summary>
        /// <returns>A string containing the list of active threads and their tasks.</returns>
        public static string TakeSnapshot()
        {
            StringBuilder threadList = new StringBuilder();

            lock (_threadsLock)
            {
                // look for an available worker thread
                for (int i = 0; i < _threads.Count; i++)
                {
                    // get the next thread
                    CustomThreadInfo customThreadInfo = (CustomThreadInfo)_threads[i];

                    // check if it's alive
                    if (!customThreadInfo.IsAlive)
                    {
                        continue;
                    }

                    if (customThreadInfo.IsIdle)
                    {
                        continue;
                    }

                    threadList.AppendFormat("Thread {0} executes \"{1}\" entry \"{2}\".{3}",
                                            customThreadInfo.Thread.Name, customThreadInfo.WorkCallback.Method.ReflectedType.ToString(),
                                            customThreadInfo.WorkCallback.Method.ToString(), Environment.NewLine);
                }
            }

            return(threadList.ToString());
        }
        /// <summary>
        /// Calculates and returns the number of occupied threads.
        /// It is not recommended to invoke this method very often.
        /// </summary>
        /// <returns>The number of occupied threads.</returns>
        public static int CalculateOccupiedThreads()
        {
            int threadsOccupied = 0;

            lock (_threadsLock)
            {
                // look for an available worker thread
                for (int i = 0; i < _threads.Count; i++)
                {
                    CustomThreadInfo customThreadInfo = (CustomThreadInfo)_threads[i];
                    if (!(customThreadInfo.IsIdle || !customThreadInfo.IsAlive))
                    {
                        threadsOccupied++;
                    }
                }
            }

            return(threadsOccupied);
        }
        /// <summary>
        /// Queues a user work item to the thread pool.
        /// </summary>
        /// <param name="callback">A WaitCallback representing the method to execute.</param>
        /// <param name="state">An object containing data to be used by the method.</param>
        /// <param name="longDuration">Indicates whether the item depends on other working threads or can take a long period to finish.</param>
        public static void QueueUserWorkItem(WaitCallback callback, object state, bool longDuration)
        {
            GenuineThreadPoolStrategy theStrategy = GenuineThreadPool.GenuineThreadPoolStrategy;

            if (callback == null)
            {
                throw new NullReferenceException("callback");
            }
            CustomThreadInfo customThreadInfo = null;

            lock (_threadsLock)
            {
                BinaryLogWriter binaryLogWriter = GenuineLoggingServices.BinaryLogWriter;
                if (binaryLogWriter != null && binaryLogWriter[LogCategory.StatisticCounters] > 0 && (Interlocked.Increment(ref _QueueUserWorkItem_OperationNumber) % GenuineThreadPool.ThreadStatisticFrequency) == 0)
                {
                    binaryLogWriter.WriteEvent(LogCategory.StatisticCounters, "GenuineThreadPool.QueueUserWorkItem",
                                               LogMessageType.ThreadPoolUsage, null, null, null, null,
                                               GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name,
                                               null, null,
                                               -1, _QueueUserWorkItem_OperationNumber, GenuineThreadPool._threads.Count, 0, null, null, null, null,
                                               "GenuineThreadPool has received a request #{0} (object \"{1}\" entry \"{2}\"). The current number of working threads: {3}. ThreadPoolAvailableThreads: {4}. MaximumThreads: {5}. CloseAfterInactivity: {6}. UnsafeQueuing: {7}. GenuineThreadPoolStrategy: {8}.",
                                               _QueueUserWorkItem_OperationNumber, callback.Method.ReflectedType.ToString(),
                                               callback.Method.ToString(),
                                               GenuineThreadPool._threads.Count,
                                               GenuineThreadPool.ThreadPoolAvailableThreads, GenuineThreadPool.MaximumThreads,
                                               GenuineThreadPool.CloseAfterInactivity.TotalMilliseconds, GenuineThreadPool.UnsafeQueuing,
                                               Enum.Format(typeof(GenuineThreadPoolStrategy), GenuineThreadPool.GenuineThreadPoolStrategy, "g")
                                               );
                }

                if (!(theStrategy == GenuineThreadPoolStrategy.AlwaysThreads ||
                      (theStrategy == GenuineThreadPoolStrategy.OnlyLongDuration && longDuration)))
                {
                    // try to use native ThreadPool if it's possible
                    int workerThreads         = 0;
                    int completionPortThreads = 0;

                    if (theStrategy == GenuineThreadPoolStrategy.SwitchAfterExhaustion)
                    {
                        ThreadPool.GetAvailableThreads(out workerThreads, out completionPortThreads);
                    }

                    if (theStrategy == GenuineThreadPoolStrategy.AlwaysNative ||
                        theStrategy == GenuineThreadPoolStrategy.OnlyLongDuration ||
                        (Math.Min(workerThreads, completionPortThreads) >= GenuineThreadPool.ThreadPoolAvailableThreads && theStrategy == GenuineThreadPoolStrategy.SwitchAfterExhaustion))
                    {
                        if (GenuineThreadPool.UnsafeQueuing)
                        {
                            ThreadPool.UnsafeQueueUserWorkItem(callback, state);
                        }
                        else
                        {
                            ThreadPool.QueueUserWorkItem(callback, state);
                        }
                        return;
                    }
                }

                // look for an available worker thread
                for (int i = 0; i < _threads.Count;)
                {
                    // get the next thread
                    customThreadInfo = (CustomThreadInfo)_threads[i];

                    // check if it's alive
                    if (!customThreadInfo.IsAlive)
                    {
                        _threads.RemoveAt(i);
                        customThreadInfo = null;
                        continue;
                    }

                    if (customThreadInfo.IsIdle)
                    {
                        break;
                    }

                    customThreadInfo = null;
                    i++;
                }

                // if the limit is exceeded
                if (customThreadInfo == null && _threads.Count >= GenuineThreadPool.MaximumThreads)
                {
                    if (GenuineThreadPool.AllowRequestQueuing)
                    {
                        _requestsQueued.Enqueue(new GenuineThreadPoolWorkItem(callback, state));
                        return;
                    }
                    else
                    {
                        throw GenuineExceptions.Get_Processing_ThreadPoolLimitExceeded();
                    }
                }

                // create a new one, if it's necessary
                if (customThreadInfo == null)
                {
                    customThreadInfo = new CustomThreadInfo(_threadsLock);
                    _threads.Add(customThreadInfo);
                }

                // give out the work
                customThreadInfo.WorkCallback  = callback;
                customThreadInfo.CallbackState = state;
                customThreadInfo.IsIdle        = false;
                customThreadInfo.ManualResetEvent.Set();
            }
        }