Beispiel #1
0
        private async Task PerformDispose(DisposeAsyncDelegate disposeDelegate = null)
        {
            var prev = Interlocked.Exchange(ref this._current, null);

            if (prev != null || disposeDelegate != null)
            {
                try
                {
                    this.IterationEndedEvent?.Invoke(null, new IterationEndedEventArgs());
                }
                catch
                {
                    // Ignore
                }
                if (disposeDelegate == null)
                {
                    disposeDelegate = prev.Dispose;
                }

                if (disposeDelegate != null)
                {
                    await prev.Dispose();
                }
            }
        }
Beispiel #2
0
 public CurrentInfo(
     T current,
     MoveNextAsyncDelegate <T> moveNext,
     DisposeAsyncDelegate disposeDelegate
     )
 {
     this.MoveNext = moveNext;
     this.Current  = current ?? throw new ArgumentNullException(nameof(current));
     this.Dispose  = disposeDelegate;
 }
Beispiel #3
0
        public async Task <Boolean> MoveNextAsync()
        {
            // We can call move next only in initial state, or after we have called it once
            Boolean retVal        = false;
            var     wasNotInitial = Interlocked.CompareExchange(ref this._state, MOVE_NEXT_STARTED, MOVE_NEXT_ENDED) == MOVE_NEXT_ENDED;

            if (wasNotInitial || Interlocked.CompareExchange(ref this._state, MOVE_NEXT_STARTED, STATE_INITIAL) == STATE_INITIAL)
            {
                DisposeAsyncDelegate disposeDelegate = null;

                try
                {
                    if (wasNotInitial)
                    {
                        var moveNext = this._current.MoveNext;
                        if (moveNext == null)
                        {
                            retVal = false;
                        }
                        else
                        {
                            T current;
                            (retVal, current) = await moveNext();

                            if (retVal)
                            {
                                this._current.Current = current;
                            }
                        }
                    }
                    else
                    {
                        // First time calling move next
                        var result = await this._initialMoveNext();

                        retVal = result.Item1;
                        if (retVal)
                        {
                            Interlocked.Exchange(ref this._current, new CurrentInfo(result.Item2, result.Item3, result.Item4));
                        }
                        else
                        {
                            disposeDelegate = result.Item4;
                        }
                    }
                }
                finally
                {
                    try
                    {
                        if (!retVal)
                        {
                            await this.PerformDispose(disposeDelegate);
                        }
                    }
                    catch
                    {
                        // Ignore.
                    }

                    if (!retVal)
                    {
                        Interlocked.Exchange(ref this._current, null);
                    }
                    Interlocked.Exchange(ref this._state, retVal ? MOVE_NEXT_ENDED : STATE_ENDED);
                }
            }
            else if (this._state != STATE_ENDED)
            {
                // Re-entrancy or concurrent with Reset -> exception
                throw new InvalidOperationException("Tried to concurrently move to next or reset.");
            }
            return(retVal);
        }