Пример #1
0
 public ValueTask DisposeAsync()
 {
     CancellationHelper.Cancel(ref _cts);
     if (Interlocked.Increment(ref _disposeWip) == 1)
     {
         if (_emitLast)
         {
             _emitLastItem = default;
         }
         return(_source.DisposeAsync());
     }
     return(ResumeHelper.Await(ref _disposeTask));
 }
Пример #2
0
            private void HandleMain(Task <bool> t)
            {
                if (t.IsCanceled)
                {
                    _error = new OperationCanceledException();
                    _done  = true;
                    if (TryDispose())
                    {
                        ResumeHelper.Resume(ref _resume);
                    }
                }
                else if (t.IsFaulted)
                {
                    CancellationHelper.Cancel(ref _cts);
                    if (_emitLast)
                    {
                        var idx = _sourceIndex;
                        if (idx != 0)
                        {
                            SetLatest(_emitLastItem, idx + 1);
                            _emitLastItem = default;
                        }
                    }
                    _error = ExceptionHelper.Extract(t.Exception);
                    _done  = true;
                    if (TryDispose())
                    {
                        ResumeHelper.Resume(ref _resume);
                    }
                }
                else if (t.Result)
                {
                    Volatile.Read(ref _cts)?.Cancel();

                    var v = _source.Current;
                    if (TryDispose())
                    {
                        if (_emitLast)
                        {
                            _emitLastItem = v;
                        }
                        var idx    = ++_sourceIndex;
                        var newCts = CancellationTokenSource.CreateLinkedTokenSource(_ct);
                        if (CancellationHelper.Replace(ref _cts, newCts))
                        {
                            Task.Delay(_delay, newCts.Token)
                            .ContinueWith(tt => TimerHandler(tt, v, idx), newCts.Token);
                            MoveNext();
                        }
                    }
                }
                else
                {
                    CancellationHelper.Cancel(ref _cts);
                    if (_emitLast)
                    {
                        var idx = _sourceIndex;
                        if (idx != 0)
                        {
                            SetLatest(_emitLastItem, idx + 1);
                            _emitLastItem = default;
                        }
                    }
                    _done = true;
                    if (TryDispose())
                    {
                        ResumeHelper.Resume(ref _resume);
                    }
                }
            }