/// <summary>
        /// Advances the enumerator to the next element of the collection asynchronously
        /// </summary>
        /// <param name="cancellationToken">A cancellation token to cancel the enumeration</param>
        /// <returns>Returns a Task that does transition to the next element. The result of the task is True if the enumerator was successfully advanced to the next element, or False if the enumerator has passed the end of the collection.</returns>
        public virtual Task <bool> MoveNextAsync(CancellationToken cancellationToken = default(CancellationToken))
        {
            if (_enumerationFunction == null)
            {
                return(TaskEx.False);
            }

            if (_yield == null)
            {
                _yield = new AsyncEnumerator <TItem> .Yield(this);
            }

            var moveNextCompleteTask = _yield.OnMoveNext(cancellationToken);

            if (_enumerationTask == null)
            {
                // Register for finalization, which might be needed if caller
                // doesn't not finish the enumeration and does not call Dispose().
                GC.ReRegisterForFinalize(this);

                _enumerationTask =
                    _enumerationFunction(_yield, State)
                    .ContinueWith(OnEnumerationCompleteAction, this, TaskContinuationOptions.ExecuteSynchronously);
            }

            return(moveNextCompleteTask);
        }
        /// <summary>
        /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources
        /// </summary>
        /// <param name="manualDispose">True if called from Dispose() method, otherwise False - called by GC</param>
        protected virtual void Dispose(bool manualDispose)
        {
            if (manualDispose)
            {
                _yield?.SetCanceled();
            }
            else if (_yield != null && !_yield.IsComplete)
            {
                var yield = _yield;
                Task.Run(() => yield.SetCanceled()); // don't block the GC thread
            }

            _enumerationTask = null;
            _yield           = null;

            _onDisposeAction?.Invoke(State);
            _onDisposeAction     = null;
            _enumerationFunction = null;
        }