private void CallWithNonPumpingWait(Action callback) { SynchronizationContext oldSynchronizationContext = SynchronizationContext.Current; NonPumpingSynchronizationContext nonPumpingSynchronizationContext = Interlocked.Exchange <NonPumpingSynchronizationContext>(ref _defaultSynchronizationContext, null); // if the default non-pumping context is in use, allocate a new one bool usingDefaultContext = (nonPumpingSynchronizationContext != null); if (!usingDefaultContext) { nonPumpingSynchronizationContext = new NonPumpingSynchronizationContext(); } try { // install the non-pumping context nonPumpingSynchronizationContext.Parent = oldSynchronizationContext; SynchronizationContext.SetSynchronizationContext(nonPumpingSynchronizationContext); // invoke the callback callback(); } finally { // restore the old context SynchronizationContext.SetSynchronizationContext(oldSynchronizationContext); // put the default non-pumping context back into play if (usingDefaultContext) { Interlocked.Exchange <NonPumpingSynchronizationContext>(ref _defaultSynchronizationContext, nonPumpingSynchronizationContext); } } }
//------------------------------------------------------ // // Constructors // //------------------------------------------------------ #region Constructors internal ReaderWriterLockWrapper() { // ideally we'd like to use the NoRecursion policy, but RWLock supports // recursion so we allow recursion for compat. It's needed for at least // one pattern - a weak event manager for an event A that delegates to // a second event B via a second weak event manager. There's at least // one instance of this within WPF (CanExecuteChanged delegates to // RequerySuggested), and it could also happen in user code. _rwLock = new ReaderWriterLockSlim(LockRecursionPolicy.SupportsRecursion); _defaultSynchronizationContext = new NonPumpingSynchronizationContext(); Initialize(!MS.Internal.BaseAppContextSwitches.EnableWeakEventMemoryImprovements); }