private void WorkItemDispatchLoop(object threadData)
        {
            var startinfo = (WorkerThreadStartParams)threadData;
            // Register a new WSQ.
            var wsq = new ThreadLocalStealQueue<ThreadPoolWorkItem>();
            wsq.Name = startinfo.ThreadName;
            _mWsq = wsq; // Store in TLS.
            AddNewWorkQueue(wsq);

            DateTime lastItemProcesTime = DateTime.UtcNow;
            try
            {
                while (true)
                {
                    if (ShouldThreadExit(lastItemProcesTime, startinfo.IsPermenant))
                    {
                        return;
                    }

                    var wi = default(ThreadPoolWorkItem);

                    // Search order: (1) local queue, (2) global Queue, (3) steal from another thread.
                    if (!wsq.LocalPop(ref wi))
                    {

                        if (ShouldThreadExit(lastItemProcesTime, startinfo.IsPermenant))
                        {
                            return;
                        }
                        lock (_mQueue)
                        {
                            // If shutdown was requested, exit the thread.
                            if (_poolStopToken.IsCancellationRequested)
                                return;

                            // (2) try the global queue.
                            if (_mQueue.Count != 0)
                            {
                                // We found a work item! Grab it …
                                wi = _mQueue.Dequeue();
                            }
                        }

                        if (wi == null)
                        {
                            lock (_mThreadLocalQueues)
                            {

                                // (3) try to steal from neighbour thread.
                                ThreadLocalStealQueue<ThreadPoolWorkItem>[] wsQueues = _mThreadLocalQueues;
                                int i;
                                for (i = 0; i < wsQueues.Length; i++)
                                {
                                    if (wsQueues[i] != null)
                                    {
                                        if (wsQueues[i] != wsq && wsQueues[i].TrySteal(ref wi))
                                            break;
                                    }
                                }
                            }
                        }
                    }

                    try
                    {
                        //we got a work item, now try to invoke it.
                        if (wi != null)
                        {
                            wi.Execute();
                            lastItemProcesTime = DateTime.UtcNow;
                        }
                    }
                    catch (Exception ex)
                    {
                        EtwLogger.Log.WorkItemFailure(ex.ToString());
                        if (UserWorkItemException != null)
                        {
                            UserWorkItemException(this, new WorkItemEventArgs
                            {
                                Exception = ex,
                                UserData = wi.UserData,
                            });
                        }
                    }

                }
            }
            finally
            {
                OnWorkerThreadExit(startinfo.ThreadName);
            }
        }