Пример #1
0
        public void WaitEventToResume(Object eventTargetToResume, long maxWaitTime, IBackgroundWorkerParamDelegate <IProcessResumeItem> resumeDelegate, IBackgroundWorkerParamDelegate <Exception> errorDelegate)
        {
            try
            {
                IdentityHashSet <Object> pendingSet = new IdentityHashSet <Object>();
                if (eventTargetToResume is IEnumerable)
                {
                    pendingSet.AddAll((IEnumerable)eventTargetToResume);
                }
                else
                {
                    pendingSet.Add(eventTargetToResume);
                }
                WaitForResumeItem pauseItem = null;
                listenersWriteLock.Lock();
                try
                {
                    IList <Object>             remainingPausedEventTargets    = EvaluatePausedEventTargetsOfForeignThreads();
                    IdentityLinkedSet <Object> remainingPausedEventTargetsSet = new IdentityLinkedSet <Object>(remainingPausedEventTargets);
                    remainingPausedEventTargetsSet.RetainAll(pendingSet);

                    if (remainingPausedEventTargetsSet.Count > 0)
                    {
                        // We should wait now but we have to check if we are in the UI thread, which must never wait
                        if (GuiThreadHelper.IsInGuiThread())
                        {
                            // This is the trick: We "requeue" the current action in the UI pipeline to prohibit blocking
                            GuiThreadHelper.InvokeInGuiLate(delegate()
                            {
                                WaitEventToResume(eventTargetToResume, maxWaitTime, resumeDelegate, errorDelegate);
                            });
                            return;
                        }
                        pauseItem = new WaitForResumeItem(pendingSet);
                        waitForResumeSet.Add(pauseItem);
                    }
                }
                finally
                {
                    listenersWriteLock.Unlock();
                }
                if (pauseItem == null)
                {
                    resumeDelegate.Invoke(null);
                    return;
                }
                CountDownLatch latch = pauseItem.Latch;
                if (maxWaitTime < 0)
                {
                    latch.Await();
                }
                else if (maxWaitTime > 0)
                {
                    latch.Await(TimeSpan.FromMilliseconds(maxWaitTime));
                }
                else
                {
                    throw new System.Exception("Thread should wait but does not want to");
                }
                resumeDelegate.Invoke(pauseItem);
            }
            catch (Exception e)
            {
                if (Log.ErrorEnabled)
                {
                    Log.Error(e);
                }
                if (errorDelegate != null)
                {
                    errorDelegate.Invoke(e);
                }
                throw;
            }
        }
Пример #2
0
        public void Resume(Object eventTarget)
        {
            if (GuiThreadHelper.IsInGuiThread())
            {
                // Nothing to do
                return;
            }
            IEventTargetExtractor eventTargetExtractor = typeToEventTargetExtractorsDict.GetExtension(eventTarget.GetType());

            if (eventTargetExtractor == null)
            {
                return;
            }
            eventTarget = eventTargetExtractor.ExtractEventTarget(eventTarget);
            if (eventTarget == null)
            {
                return;
            }
            IdentityLinkedSet <WaitForResumeItem> freeLatchMap = null;

            try
            {
                PausedEventTargetItem pauseETI;
                listenersWriteLock.Lock();
                try
                {
                    IdentityLinkedMap <Object, PausedEventTargetItem> pausedTargets = this.pausedTargets;
                    pauseETI = pausedTargets.Get(eventTarget);
                    if (pauseETI == null)
                    {
                        throw new System.Exception("No pause() active for target " + eventTarget);
                    }
                    pauseETI.PauseCount--;
                    if (pauseETI.PauseCount > 0)
                    {
                        return;
                    }
                    pausedTargets.Remove(eventTarget);

                    IList <Object>               remainingPausedEventTargets    = EvaluatePausedEventTargets();
                    IdentityHashSet <Object>     remainingPausedEventTargetsSet = new IdentityHashSet <Object>();
                    Iterator <WaitForResumeItem> iter = waitForResumeSet.Iterator();
                    while (iter.MoveNext())
                    {
                        WaitForResumeItem pauseItem = iter.Current;
                        remainingPausedEventTargetsSet.AddAll(remainingPausedEventTargets);
                        remainingPausedEventTargetsSet.RetainAll(pauseItem.PendingPauses);

                        if (remainingPausedEventTargetsSet.Count == 0)
                        {
                            iter.Remove();
                            if (freeLatchMap == null)
                            {
                                freeLatchMap = new IdentityLinkedSet <WaitForResumeItem>();
                            }
                            freeLatchMap.Add(pauseItem);
                        }
                        remainingPausedEventTargetsSet.Clear();
                    }
                }
                finally
                {
                    listenersWriteLock.Unlock();
                }
            }
            finally
            {
                if (freeLatchMap != null)
                {
                    foreach (WaitForResumeItem wfrItem in freeLatchMap)
                    {
                        wfrItem.Latch.CountDown();
                    }
                    foreach (WaitForResumeItem wfrItem in freeLatchMap)
                    {
                        try
                        {
                            wfrItem.ResultLatch.Await();
                        }
                        catch (System.Exception e)
                        {
                            throw new System.Exception("Fatal state occured. This may result in a global deadlock", e);
                        }
                    }
                }
            }
        }