diff --git a/Rx.NET/Source/src/System.Reactive/Linq/Observable/Finally.cs b/Rx.NET/Source/src/System.Reactive/Linq/Observable/Finally.cs index 48d04645c4..c3a23333e1 100644 --- a/Rx.NET/Source/src/System.Reactive/Linq/Observable/Finally.cs +++ b/Rx.NET/Source/src/System.Reactive/Linq/Observable/Finally.cs @@ -3,6 +3,7 @@ // See the LICENSE file in the project root for more information. using System.Reactive.Disposables; +using System.Threading; namespace System.Reactive.Linq.ObservableImpl { @@ -24,6 +25,7 @@ public Finally(IObservable source, Action finallyAction) internal sealed class _ : IdentitySink { private readonly Action _finallyAction; + private IDisposable _sourceDisposable; public _(Action finallyAction, IObserver observer) : base(observer) @@ -33,19 +35,43 @@ public _(Action finallyAction, IObserver observer) public override void Run(IObservable source) { - var subscription = source.SubscribeSafe(this); + var d = source.SubscribeSafe(this); - SetUpstream(Disposable.Create(() => + if (Interlocked.CompareExchange(ref _sourceDisposable, d, null) == BooleanDisposable.True) { + // The Dispose(bool) methode was already called before the + // subscription could be assign, hence the subscription + // needs to be diposed here and the action needs to be invoked. try { - subscription.Dispose(); + d.Dispose(); } finally { _finallyAction(); } - })); + } + } + + protected override void Dispose(bool disposing) + { + base.Dispose(disposing); + + if (disposing) + { + var d = Interlocked.Exchange(ref _sourceDisposable, BooleanDisposable.True); + if (d != BooleanDisposable.True && d != null) + { + try + { + d.Dispose(); + } + finally + { + _finallyAction(); + } + } + } } } }