/// <summary> /// If a scope is active, buffers the event. Otherwise, directly raises it. /// </summary> public static void RaiseOrBufferEvent(Action raiseEvent) { if (Current != null) { tracer.Verbose(Resources.StoreEventBufferingScope_BufferingEvent); Current.AddEvent(raiseEvent); } else { raiseEvent(); } }
/// <summary> /// Releases unmanaged and - optionally - managed resources. /// </summary> protected virtual void Dispose(bool disposing) { if (!this.disposed) { while (Current != this && Current != null) { Current.IsCanceled = this.IsCanceled; // This would automatically pop the nested scopes. Current.Dispose(); } // Pop myself now. scopes.Pop(); if (this.IsCanceled) { tracer.Verbose(Resources.StoreEventBufferingScope_CancelledScopeIgnoringEvent); // If we have been cancelled, we don't waste time copying our events to the potential parent // scope as they will never be raised anyways. } else if (this.completed || this.autoComplete) { if (Current != null) { tracer.Verbose(Resources.StoreEventBufferingScope_CompleteEnqueingOnParent); // There's another parent scope. Append our events to the // end of its queue for it to raise them later when it is itself // disposed in turn. this.events.ForEach(ev => Current.AddEvent(ev)); } else { tracer.Verbose(Resources.StoreEventBufferingScope_RaisingEvents); // We're the topmost scope, so we raise all buffered events now. foreach (var raiseEvent in this.events) { RaisingEvents = true; try { raiseEvent(); } finally { RaisingEvents = false; } } } } else { tracer.Verbose(Resources.StoreEventBufferingScope_DisposingNonComplete); } // Propagate cancellation flag upwards. if (Current != null) { Current.IsCanceled = this.IsCanceled; } this.disposed = true; } }