// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information. #if !NO_SYNCCTX using System.Reactive.Concurrency; using System.Threading; namespace System.Reactive.Disposables { /// /// Represents a disposable resource whose disposal invocation will be posted to the specified . /// public sealed class ContextDisposable : ICancelable { private readonly SynchronizationContext _context; private volatile IDisposable _disposable; /// /// Initializes a new instance of the class that uses the specified on which to dispose the specified disposable resource. /// /// Context to perform disposal on. /// Disposable whose Dispose operation to run on the given synchronization context. /// or is null. public ContextDisposable(SynchronizationContext context, IDisposable disposable) { if (context == null) throw new ArgumentNullException("context"); if (disposable == null) throw new ArgumentNullException("disposable"); _context = context; _disposable = disposable; } /// /// Gets the provided . /// public SynchronizationContext Context { get { return _context; } } /// /// Gets a value that indicates whether the object is disposed. /// public bool IsDisposed { get { return _disposable == BooleanDisposable.True; } } /// /// Disposes the underlying disposable on the provided . /// public void Dispose() { #pragma warning disable 0420 var disposable = Interlocked.Exchange(ref _disposable, BooleanDisposable.True); #pragma warning restore 0420 if (disposable != BooleanDisposable.True) { _context.PostWithStartComplete(d => d.Dispose(), disposable); } } } } #endif