static IEnumerator WrapEnumeratorYieldValue <T>(IEnumerator enumerator, IObserver <T> observer, CancellationToken cancellationToken, bool nullAsNextUpdate) { bool hasNext = default(bool); object current = default(object); bool raisedError = false; do { try { hasNext = enumerator.MoveNext(); if (hasNext) { current = enumerator.Current; } } catch (Exception ex) { try { raisedError = true; observer.OnError(ex); } finally { IDisposable d = enumerator as IDisposable; if (d != null) { d.Dispose(); } } yield break; } if (hasNext) { if (current != null && YieldInstructionTypes.Contains(current.GetType())) { yield return(current); } #if SupportCustomYieldInstruction else if (current is IEnumerator) { ICustomYieldInstructionErrorHandler customHandler = current as ICustomYieldInstructionErrorHandler; if (customHandler != null && customHandler.IsReThrowOnError) { // If throws exception in Custom YieldInsrtuction, can't handle parent coroutine. // It is C# limitation. // so store error info and retrieve from parent. customHandler.ForceDisableRethrowOnError(); yield return(current); customHandler.ForceEnableRethrowOnError(); if (customHandler.HasError) { try { raisedError = true; observer.OnError(customHandler.Error); } finally { IDisposable d = enumerator as IDisposable; if (d != null) { d.Dispose(); } } yield break; } } else { yield return(current); } } #endif else if (current == null && nullAsNextUpdate) { yield return(null); } else { try { observer.OnNext((T)current); } catch { IDisposable d = enumerator as IDisposable; if (d != null) { d.Dispose(); } throw; } } } } while (hasNext && !cancellationToken.IsCancellationRequested); try { if (!raisedError && !cancellationToken.IsCancellationRequested) { observer.OnCompleted(); } } finally { IDisposable d = enumerator as IDisposable; if (d != null) { d.Dispose(); } } }
static IEnumerator WrapEnumerator(IEnumerator enumerator, IObserver <Unit> observer, CancellationToken cancellationToken, bool publishEveryYield) { bool hasNext = default(bool); bool raisedError = false; do { try { hasNext = enumerator.MoveNext(); } catch (Exception ex) { try { raisedError = true; observer.OnError(ex); } finally { IDisposable d = enumerator as IDisposable; if (d != null) { d.Dispose(); } } yield break; } if (hasNext && publishEveryYield) { try { observer.OnNext(Unit.Default); } catch { IDisposable d = enumerator as IDisposable; if (d != null) { d.Dispose(); } throw; } } if (hasNext) { #if SupportCustomYieldInstruction object current = enumerator.Current; ICustomYieldInstructionErrorHandler customHandler = current as ICustomYieldInstructionErrorHandler; if (customHandler != null && customHandler.IsReThrowOnError) { // If throws exception in Custom YieldInsrtuction, can't handle parent coroutine. // It is C# limitation. // so store error info and retrieve from parent. customHandler.ForceDisableRethrowOnError(); yield return(current); customHandler.ForceEnableRethrowOnError(); if (customHandler.HasError) { try { raisedError = true; observer.OnError(customHandler.Error); } finally { IDisposable d = enumerator as IDisposable; if (d != null) { d.Dispose(); } } yield break; } } else { yield return(enumerator.Current); // yield inner YieldInstruction } #else yield return(enumerator.Current); // yield inner YieldInstruction #endif } } while (hasNext && !cancellationToken.IsCancellationRequested); try { if (!raisedError && !cancellationToken.IsCancellationRequested) { observer.OnNext(Unit.Default); // last one observer.OnCompleted(); } } finally { IDisposable d = enumerator as IDisposable; if (d != null) { d.Dispose(); } } }