From 35757bd0820405deae38c424f4197ed73a1d6dea Mon Sep 17 00:00:00 2001 From: Daniel Weber Date: Fri, 6 Jul 2018 09:37:53 +0200 Subject: [PATCH 1/2] Sink.Dispose should only call Dispose(true) once. --- Rx.NET/Source/src/System.Reactive/Internal/Sink.cs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/Rx.NET/Source/src/System.Reactive/Internal/Sink.cs b/Rx.NET/Source/src/System.Reactive/Internal/Sink.cs index 3ddfba9251..173aba5157 100644 --- a/Rx.NET/Source/src/System.Reactive/Internal/Sink.cs +++ b/Rx.NET/Source/src/System.Reactive/Internal/Sink.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 { @@ -25,12 +26,16 @@ protected Sink(IObserver observer) public void Dispose() { - Dispose(true); + if (_observer != NopObserver.Instance && Interlocked.Exchange(ref _observer, NopObserver.Instance) != NopObserver.Instance) + Dispose(true); } protected virtual void Dispose(bool disposing) { - _observer = NopObserver.Instance; + //Calling base.Dispose(true) is not a proper disposal, so we can omit the assignment here. + //Sink is internal so this can pretty much be enforced. + //_observer = NopObserver.Instance; + Disposable.TryDispose(ref _upstream); } From 9682ba031edcd38aba39b0ca58b26a9a2aa9e4bd Mon Sep 17 00:00:00 2001 From: Daniel Weber Date: Fri, 6 Jul 2018 10:00:41 +0200 Subject: [PATCH 2/2] Don't check Sink._observer upfront because for a reasonable number of expected calls (< 3), the benefit will not show. --- Rx.NET/Source/src/System.Reactive/Internal/Sink.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Rx.NET/Source/src/System.Reactive/Internal/Sink.cs b/Rx.NET/Source/src/System.Reactive/Internal/Sink.cs index 173aba5157..a4c21fb01c 100644 --- a/Rx.NET/Source/src/System.Reactive/Internal/Sink.cs +++ b/Rx.NET/Source/src/System.Reactive/Internal/Sink.cs @@ -26,7 +26,7 @@ protected Sink(IObserver observer) public void Dispose() { - if (_observer != NopObserver.Instance && Interlocked.Exchange(ref _observer, NopObserver.Instance) != NopObserver.Instance) + if (Interlocked.Exchange(ref _observer, NopObserver.Instance) != NopObserver.Instance) Dispose(true); }