@@ -242,7 +242,8 @@ sealed class MergeEnumerableSubscription : IAsyncDisposable
242242 readonly TaskCompletionSource < bool > _subscriptionFinished = new ( TaskCreationOptions . RunContinuationsAsynchronously ) ;
243243 readonly AsyncLocal < bool > _reentrant = new ( ) ;
244244 int _active ;
245- int _disposed ;
245+ bool _enumerationCompleted ;
246+ bool _disposed ;
246247 readonly AsyncObserver < T > _observer ;
247248
248249 public MergeEnumerableSubscription ( AsyncObserver < T > observer , IEnumerable < AsyncObservable < T > > sources )
@@ -261,7 +262,11 @@ public async void StartAsync()
261262 {
262263 foreach ( var src in _sources )
263264 {
264- Interlocked . Increment ( ref _active ) ;
265+ _disposedCancellationToken . ThrowIfCancellationRequested ( ) ;
266+ lock ( _onSomethingGate )
267+ {
268+ _active ++ ;
269+ }
265270
266271 var innerObserver = new InnerAsyncObserver ( this ) ;
267272 await _innerDisposables . AddAsync ( innerObserver ) ;
@@ -280,7 +285,14 @@ public async void StartAsync()
280285 }
281286 }
282287
283- if ( Volatile . Read ( ref _active ) == 0 )
288+ bool shouldComplete ;
289+ lock ( _onSomethingGate )
290+ {
291+ _enumerationCompleted = true ;
292+ shouldComplete = _active == 0 ;
293+ }
294+
295+ if ( shouldComplete )
284296 {
285297 await CompleteAsync ( Result . Success ) ;
286298 }
@@ -305,7 +317,7 @@ async ValueTask OnNextAsync(T value, CancellationToken token)
305317 using var linked = CancellationTokenSource . CreateLinkedTokenSource ( _disposedCancellationToken , token ) ;
306318 using ( await _onSomethingGate . LockAsync ( ) )
307319 {
308- if ( _disposed == 1 ) return ;
320+ if ( _disposed ) return ;
309321 await _observer . OnNextAsync ( value , linked . Token ) ;
310322 }
311323 }
@@ -315,7 +327,7 @@ async ValueTask OnErrorResumeAsync(Exception ex, CancellationToken token)
315327 using var linked = CancellationTokenSource . CreateLinkedTokenSource ( _disposedCancellationToken , token ) ;
316328 using ( await _onSomethingGate . LockAsync ( ) )
317329 {
318- if ( _disposed == 1 ) return ;
330+ if ( _disposed ) return ;
319331 await _observer . OnErrorResumeAsync ( ex , linked . Token ) ;
320332 }
321333 }
@@ -327,21 +339,28 @@ ValueTask OnCompletedAsync(Result result)
327339 return CompleteAsync ( result ) ;
328340 }
329341
330- if ( Interlocked . Decrement ( ref _active ) == 0 )
342+ bool shouldComplete ;
343+ lock ( _onSomethingGate )
331344 {
332- return CompleteAsync ( Result . Success ) ;
345+ _active -- ;
346+ shouldComplete = _active == 0 && _enumerationCompleted ;
333347 }
334348
335- return default ;
349+ return shouldComplete ? CompleteAsync ( Result . Success ) : default ;
336350 }
337351
338352 async ValueTask CompleteAsync ( Result ? result )
339353 {
340- if ( Interlocked . Exchange ( ref _disposed , 1 ) == 1 )
354+ using ( await _onSomethingGate . LockAsync ( ) )
341355 {
342- if ( result ? . Exception is not null and var ex )
343- UnhandledExceptionHandler . OnUnhandledException ( ex ) ;
344- return ;
356+ if ( _disposed )
357+ {
358+ if ( result ? . Exception is not null and var ex )
359+ UnhandledExceptionHandler . OnUnhandledException ( ex ) ;
360+ return ;
361+ }
362+
363+ _disposed = true ;
345364 }
346365
347366 _cts . Cancel ( ) ;
0 commit comments