コード例 #1
0
        private void CallbackWrapper(object state)
        {
            DispatcherItem     item         = (DispatcherItem)state;
            SendOrPostCallback userCallback = item.UserCallback;
            object             userContext  = item.UserContext;

            try
            {
                userCallback(userContext);
            }
            catch (Exception excp)
            {
                _Dispatcher.SetLastException(excp);
                _Dispatcher.Logger.Log(excp);
            }
            _Dispatcher.DecOutstanding();

            // now dispatch any waiting items
            ProcessNode(item);
        }
コード例 #2
0
        private void ProcessNode(DispatcherItem completedItem)
        {
            long threadsInTree = IncThreadsInTree();

            try
            {
                if (completedItem != null)
                {
                    // completed item cleanup
                    DecThreadsInTree();
                    long debugN = Interlocked.Decrement(ref _ThisNodeRunning);
                    Debug.Assert(debugN == 0);
                    _Parent?.DecChildrenRunning();
                    completedItem = null;
                }

                bool looping = true;
                while (looping)
                {
                    looping = false;
                    // ensure that at least one pass through the dequeuing logic occurs
                    _Queue.Locked((queue) =>
                    {
                        // we have the queue
                        // we can dispatch the head of the queue if:
                        // a) the item is for this level, AND this tree is not running;
                        // or b) the item is for a lower level, AND this node is not running.
                        if (queue.Count > 0)
                        {
                            DispatcherItem workItem = queue.Peek();
                            Debug.Assert(workItem.Level >= _Level);
                            if ((workItem.Level == _Level) &&
                                (Interlocked.Add(ref _ThisNodeRunning, 0) == 0) &&
                                (Interlocked.Add(ref _ChildrenRunning, 0) == 0))
                            {
                                // item is for this level
                                // dispatch it to the threadpool
                                queue.Dequeue();
                                long debugN = Interlocked.Increment(ref _ThisNodeRunning);
                                Debug.Assert(debugN == 1);
                                IncThreadsInTree();
                                ThreadPool.QueueUserWorkItem(CallbackWrapper, workItem);
                            }
                            if ((workItem.Level > _Level) &&
                                (Interlocked.Add(ref _ThisNodeRunning, 0) == 0))
                            {
                                // item is for lower level
                                // enqueue it to the child
                                queue.Dequeue();
                                Interlocked.Increment(ref _ChildrenRunning);
                                DispatcherNode childNode = workItem.NodeList[_Level + 1];
                                childNode.Enqueue(workItem);
                                // dequeue next
                                looping = true;
                            }
                        }
                    });
                } // while looping
            }
            finally
            {
                threadsInTree = DecThreadsInTree();
            }
            if ((threadsInTree == 0) && (_Parent != null))
            {
                // we are the last thread in this tree - handoff to parent
                ThreadPool.QueueUserWorkItem(_Parent.AsyncProcessNode, null);
            }
        }
コード例 #3
0
 internal void Enqueue(DispatcherItem item)
 {
     _Queue.Locked((queue) => queue.Enqueue(item));
     ThreadPool.QueueUserWorkItem(AsyncProcessNode, null);
 }