Exemple #1
0
 public void SetShadowSources(double k)
 {
     var sArray = new TSource[2 * ParallelBeams.Length];
     for (int i1 = 0; i1 < ParallelBeams.Length; ++i1)
     {
         int i = 2 * i1;
         sArray[i] = ParallelBeams[i1];
         sArray[i + 1].O = -sArray[i].O;
         sArray[i + 1].C = -k * sArray[i].C;
     }
     ParallelBeams = sArray;
 }
Exemple #2
0
 public DelayObserver(_ parent, TSource value)
 {
     _parent = parent;
     _value  = value;
 }
Exemple #3
0
 public void Map(TSource source, TTarget target)
 {
     _action(target, _property(source));
 }
Exemple #4
0
            //---------------------------------------------------------------------------------------
            // Straightforward IEnumerator<T> methods.
            //

            internal override bool MoveNext([MaybeNullWhen(false), AllowNull] ref TSource currentElement, ref int currentKey)
            {
                Debug.Assert(_source != null);

                if (_alreadySearched)
                {
                    return(false);
                }

                // Look for the greatest element.
                TSource candidate      = default(TSource) !;
                TKey    candidateKey   = default(TKey) !;
                bool    candidateFound = false;

                try
                {
                    int     loopCount = 0; //counter to help with cancellation
                    TSource value     = default(TSource) !;
                    TKey    key       = default(TKey) !;
                    while (_source.MoveNext(ref value !, ref key))
                    {
                        if ((loopCount & CancellationState.POLL_INTERVAL) == 0)
                        {
                            _cancellationToken.ThrowIfCancellationRequested();
                        }
                        ;

                        // If the predicate is null or the current element satisfies it, we will remember
                        // it as the current partition's candidate for the last element, and move on.
                        if (_predicate == null || _predicate(value))
                        {
                            candidate      = value;
                            candidateKey   = key;
                            candidateFound = true;
                        }

                        loopCount++;
                    }

                    // If we found a candidate element, try to publish it, so long as it's greater.
                    if (candidateFound)
                    {
                        lock (_operatorState)
                        {
                            if (_operatorState._partitionId == -1 || _keyComparer.Compare(candidateKey, _operatorState._key) > 0)
                            {
                                _operatorState._partitionId = _partitionId;
                                _operatorState._key         = candidateKey;
                            }
                        }
                    }
                }
                finally
                {
                    // No matter whether we exit due to an exception or normal completion, we must ensure
                    // that we signal other partitions that we have completed.  Otherwise, we can cause deadlocks.
                    _sharedBarrier.Signal();
                }

                _alreadySearched = true;

                // Only if we have a candidate do we wait.
                if (_partitionId == _operatorState._partitionId)
                {
                    _sharedBarrier.Wait(_cancellationToken);

                    // Now re-read the shared index. If it's the same as ours, we won and return true.
                    if (_operatorState._partitionId == _partitionId)
                    {
                        currentElement = candidate;
                        currentKey     = 0; // 1st (and only) element, so we hardcode the output index to 0.
                        return(true);
                    }
                }

                // If we got here, we didn't win. Return false.
                return(false);
            }
 public TransformedItemContainer(TSource source, TDestination destination)
 {
     Source      = source;
     Destination = destination;
 }
Exemple #6
0
 public SingleImmediate(IObservable <TSource> source, TSource value, bool append)
     : base(source, value, append)
 {
 }
Exemple #7
0
        public static IAsyncEnumerable <TSource> Merge <TSource>(params IAsyncEnumerable <TSource>[] sources)
        {
            if (sources == null)
            {
                throw Error.ArgumentNull(nameof(sources));
            }

#if USE_FAIR_AND_CHEAPER_MERGE
            //
            // This new implementation of Merge differs from the original one in a few ways:
            //
            // - It's cheaper because:
            //   - no conversion from ValueTask<bool> to Task<bool> takes place using AsTask,
            //   - we don't instantiate Task.WhenAny tasks for each iteration.
            // - It's fairer because:
            //   - the MoveNextAsync tasks are awaited concurently, but completions are queued,
            //     instead of awaiting a new WhenAny task where "left" sources have preferential
            //     treatment over "right" sources.
            //

            return(AsyncEnumerable.Create(Core));

            async IAsyncEnumerator <TSource> Core(CancellationToken cancellationToken)
            {
                var count = sources.Length;

                var enumerators   = new IAsyncEnumerator <TSource> [count];
                var moveNextTasks = new ValueTask <bool> [count];

                try
                {
                    for (var i = 0; i < count; i++)
                    {
                        IAsyncEnumerator <TSource> enumerator = sources[i].GetAsyncEnumerator(cancellationToken);
                        enumerators[i] = enumerator;

                        // REVIEW: This follows the lead of the original implementation where we kick off MoveNextAsync
                        //         operations immediately. An alternative would be to do this in a separate stage, thus
                        //         preventing concurrency across MoveNextAsync and GetAsyncEnumerator calls and avoiding
                        //         any MoveNextAsync calls before all enumerators are acquired (or an exception has
                        //         occurred doing so).

                        moveNextTasks[i] = enumerator.MoveNextAsync();
                    }

                    var whenAny = TaskExt.WhenAny(moveNextTasks);

                    int active = count;

                    while (active > 0)
                    {
                        int index = await whenAny;

                        IAsyncEnumerator <TSource> enumerator   = enumerators[index];
                        ValueTask <bool>           moveNextTask = moveNextTasks[index];

                        if (!await moveNextTask.ConfigureAwait(false))
                        {
                            //
                            // Replace the task in our array by a completed task to make finally logic easier. Note that
                            // the WhenAnyValueTask object has a reference to our array (i.e. no copy is made), so this
                            // gets rid of any resources the original task may have held onto. However, we *don't* call
                            // whenAny.Replace to set this value, because it'd attach an awaiter to the already completed
                            // task, causing spurious wake-ups when awaiting whenAny.
                            //

                            moveNextTasks[index] = new ValueTask <bool>();

                            // REVIEW: The original implementation did not dispose eagerly, which could lead to resource
                            //         leaks when merged with other long-running sequences.

                            enumerators[index] = null; // NB: Avoids attempt at double dispose in finally if disposing fails.
                            await enumerator.DisposeAsync().ConfigureAwait(false);

                            active--;
                        }
                        else
                        {
                            TSource item = enumerator.Current;

                            //
                            // Replace the task using whenAny.Replace, which will write it to the moveNextTasks array, and
                            // will start awaiting the task. Note we don't have to write to moveNextTasks ourselves because
                            // the whenAny object has a reference to it (i.e. no copy is made).
                            //

                            whenAny.Replace(index, enumerator.MoveNextAsync());

                            yield return(item);
                        }
                    }
                }
                finally
                {
                    // REVIEW: The original implementation performs a concurrent dispose, which seems undesirable given the
                    //         additional uncontrollable source of concurrency and the sequential resource acquisition. In
                    //         this modern implementation, we release resources in opposite order as we acquired them, thus
                    //         guaranteeing determinism (and mimicking a series of nested `await using` statements).

                    // REVIEW: If we decide to phase GetAsyncEnumerator and the initial MoveNextAsync calls at the start of
                    //         the operator implementation, we should make this symmetric and first await all in flight
                    //         MoveNextAsync operations, prior to disposing the enumerators.

                    var errors = default(List <Exception>);

                    for (var i = count - 1; i >= 0; i--)
                    {
                        ValueTask <bool>           moveNextTask = moveNextTasks[i];
                        IAsyncEnumerator <TSource> enumerator   = enumerators[i];

                        try
                        {
                            try
                            {
                                //
                                // Await the task to ensure outstanding work is completed prior to performing a dispose
                                // operation. Note that we don't have to do anything special for tasks belonging to
                                // enumerators that have finished; we swapped in a placeholder completed task.
                                //

                                // REVIEW: This adds an additional continuation to all of the pending tasks (note that
                                //         whenAny also has registered one). The whenAny object will be collectible
                                //         after all of these complete. Alternatively, we could drain via whenAny, by
                                //         awaiting it until the active count drops to 0. This saves on attaching the
                                //         additional continuations, but we need to decide on order of dispose. Right
                                //         now, we dispose in opposite order of acquiring the enumerators, with the
                                //         exception of enumerators that were disposed eagerly upon early completion.
                                //         Should we care about the dispose order at all?

                                _ = await moveNextTask.ConfigureAwait(false);
                            }
                            finally
                            {
                                if (enumerator != null)
                                {
                                    await enumerator.DisposeAsync().ConfigureAwait(false);
                                }
                            }
                        }
                        catch (Exception ex)
                        {
                            if (errors == null)
                            {
                                errors = new List <Exception>();
                            }

                            errors.Add(ex);
                        }
                    }

                    // NB: If we had any errors during cleaning (and awaiting pending operations), we throw these exceptions
                    //     instead of the original exception that may have led to running the finally block. This is similar
                    //     to throwing from any finally block (except that we catch all exceptions to ensure cleanup of all
                    //     concurrent sequences being merged).

                    if (errors != null)
                    {
                        throw new AggregateException(errors);
                    }
                }
            }
#else
            return(AsyncEnumerable.Create(Core));

            async IAsyncEnumerator <TSource> Core(CancellationToken cancellationToken)
            {
                var count = sources.Length;

                var enumerators   = new IAsyncEnumerator <TSource>?[count];
                var moveNextTasks = new Task <bool> [count];

                try
                {
                    for (var i = 0; i < count; i++)
                    {
                        var enumerator = sources[i].GetAsyncEnumerator(cancellationToken);
                        enumerators[i] = enumerator;

                        // REVIEW: This follows the lead of the original implementation where we kick off MoveNextAsync
                        //         operations immediately. An alternative would be to do this in a separate stage, thus
                        //         preventing concurrency across MoveNextAsync and GetAsyncEnumerator calls and avoiding
                        //         any MoveNextAsync calls before all enumerators are acquired (or an exception has
                        //         occurred doing so).

                        moveNextTasks[i] = enumerator.MoveNextAsync().AsTask();
                    }

                    var active = count;

                    while (active > 0)
                    {
                        // REVIEW: Performance of WhenAny may be an issue when called repeatedly like this. We should
                        //         measure and could consider operating directly on the ValueTask<bool> objects, thus
                        //         also preventing the Task<bool> allocations from AsTask.

                        var moveNextTask = await Task.WhenAny(moveNextTasks).ConfigureAwait(false);

                        // REVIEW: This seems wrong. AsTask can return the original Task<bool> (if the ValueTask<bool>
                        //         is wrapping one) or return a singleton instance for true and false, at which point
                        //         the use of IndexOf may pick an element closer to the start of the array because of
                        //         reference equality checks and aliasing effects. See GetTaskForResult in the BCL.

                        var index = Array.IndexOf(moveNextTasks, moveNextTask);

                        var enumerator = enumerators[index] !; // NB: Only gets set to null after setting task to Never.

                        if (!await moveNextTask.ConfigureAwait(false))
                        {
                            moveNextTasks[index] = TaskExt.Never;

                            // REVIEW: The original implementation did not dispose eagerly, which could lead to resource
                            //         leaks when merged with other long-running sequences.

                            enumerators[index] = null; // NB: Avoids attempt at double dispose in finally if disposing fails.
                            await enumerator.DisposeAsync().ConfigureAwait(false);

                            active--;
                        }
                        else
                        {
                            var item = enumerator.Current;

                            moveNextTasks[index] = enumerator.MoveNextAsync().AsTask();

                            yield return(item);
                        }
                    }
                }
                finally
                {
                    // REVIEW: The original implementation performs a concurrent dispose, which seems undesirable given the
                    //         additional uncontrollable source of concurrency and the sequential resource acquisition. In
                    //         this modern implementation, we release resources in opposite order as we acquired them, thus
                    //         guaranteeing determinism (and mimicking a series of nested `await using` statements).

                    // REVIEW: If we decide to phase GetAsyncEnumerator and the initial MoveNextAsync calls at the start of
                    //         the operator implementation, we should make this symmetric and first await all in flight
                    //         MoveNextAsync operations, prior to disposing the enumerators.

                    var errors = default(List <Exception>);

                    for (var i = count - 1; i >= 0; i--)
                    {
                        var moveNextTask = moveNextTasks[i];
                        var enumerator   = enumerators[i];

                        try
                        {
                            try
                            {
                                if (moveNextTask != null && moveNextTask != TaskExt.Never)
                                {
                                    _ = await moveNextTask.ConfigureAwait(false);
                                }
                            }
                            finally
                            {
                                if (enumerator != null)
                                {
                                    await enumerator.DisposeAsync().ConfigureAwait(false);
                                }
                            }
                        }
                        catch (Exception ex)
                        {
                            if (errors == null)
                            {
                                errors = new List <Exception>();
                            }

                            errors.Add(ex);
                        }
                    }

                    // NB: If we had any errors during cleaning (and awaiting pending operations), we throw these exceptions
                    //     instead of the original exception that may have led to running the finally block. This is similar
                    //     to throwing from any finally block (except that we catch all exceptions to ensure cleanup of all
                    //     concurrent sequences being merged).

                    if (errors != null)
                    {
                        throw new AggregateException(errors);
                    }
                }
            }
#endif
        }
Exemple #8
0
 public ThrottleObserver(_ parent, TSource value, ulong currentid)
 {
     _parent    = parent;
     _value     = value;
     _currentid = currentid;
 }
Exemple #9
0
 public Delta(_ parent, TSource value, IDisposable self)
 {
     _parent = parent;
     _value  = value;
     _self   = self;
 }
Exemple #10
0
 internal DefaultIfEmptyQueryOperatorEnumerator(QueryOperatorEnumerator <TSource, TKey> source, TSource defaultValue, int partitionIndex, int partitionCount, Shared <int> sharedEmptyCount, CountdownEvent sharedLatch, CancellationToken cancelToken)
 {
     this.m_source           = source;
     this.m_defaultValue     = defaultValue;
     this.m_partitionIndex   = partitionIndex;
     this.m_partitionCount   = partitionCount;
     this.m_sharedEmptyCount = sharedEmptyCount;
     this.m_sharedLatch      = sharedLatch;
     this.m_cancelToken      = cancelToken;
 }
Exemple #11
0
 public void Update(TSource v, long i, bool t)
 {
     Value   = v;
     Index   = i;
     IsValid = t;
 }
Exemple #12
0
 private void RestartState()
 {
     _stage._close(_blockingStream);
     _blockingStream = _stage._create();
     _open           = true;
 }
Exemple #13
0
 public override void PreStart()
 {
     _blockingStream = _stage._create();
     _open           = true;
 }
Exemple #14
0
            public void OnNext(TSource value)
            {
                var key = default(TKey);

                try
                {
                    key = _keySelector(value);
                }
                catch (Exception exception)
                {
                    Error(exception);
                    return;
                }

                var fireNewMapEntry = false;
                var writer          = default(ISubject <TElement>);

                try
                {
                    //
                    // Note: The box instruction in the IL will be erased by the JIT in case T is
                    //       a value type. In fact, the whole if block will go away and we'll end
                    //       up with nothing but the GetOrAdd call below.
                    //
                    //       See GroupBy for more information and confirmation of this fact using
                    //       the SOS debugger extension.
                    //
                    if (key == null)
                    {
                        lock (_nullGate)
                        {
                            if (_null == null)
                            {
                                _null           = NewSubject();
                                fireNewMapEntry = true;
                            }

                            writer = _null;
                        }
                    }
                    else
                    {
                        writer = _map.GetOrAdd(key, NewSubject, out fireNewMapEntry);
                    }
                }
                catch (Exception exception)
                {
                    Error(exception);
                    return;
                }

                if (fireNewMapEntry)
                {
                    var group = new GroupedObservable <TKey, TElement>(key, writer, _refCountDisposable);

                    var duration = default(IObservable <TDuration>);

                    var durationGroup = new GroupedObservable <TKey, TElement>(key, writer);
                    try
                    {
                        duration = _durationSelector(durationGroup);
                    }
                    catch (Exception exception)
                    {
                        Error(exception);
                        return;
                    }

                    lock (base._observer)
                        base._observer.OnNext(group);

                    var md = new SingleAssignmentDisposable();
                    _groupDisposable.Add(md);
                    md.Disposable = duration.SubscribeSafe(new DurationObserver(this, key, writer, md));
                }

                var element = default(TElement);

                try
                {
                    element = _elementSelector(value);
                }
                catch (Exception exception)
                {
                    Error(exception);
                    return;
                }

                //
                // ISSUE: Rx v1.x shipped without proper handling of the case where the duration
                //        sequence fires concurrently with the OnNext code path here. In such a
                //        case, the subject can be completed before we get a chance to send out
                //        a new element. However, a resurrected group for the same key won't get
                //        to see the element either. To guard against this case, we'd have to
                //        check whether the OnNext call below lost the race, and resurrect a new
                //        group if needed. Unfortunately, this complicates matters when the
                //        duration selector triggers synchronously (e.g. Return or Empty), which
                //        causes the group to terminate immediately. We should not get stuck in
                //        this case, repeatedly trying to resurrect a group that always ends
                //        before we can send the element into it. Also, users may expect this
                //        base case to mean no elements will ever be produced, so sending the
                //        element into the group before starting the duration sequence may not
                //        be a good idea either. For the time being, we'll leave this as-is and
                //        revisit the behavior for vNext. Nonetheless, we'll add synchronization
                //        to ensure no concurrent calls to the subject are made.
                //
                writer.OnNext(element);
            }
 protected override TTarget SafeOnNext(TSource value) => this.mapping(value);
Exemple #16
0
 public SubSourcePair(INotifyValue <IEnumerable <TIntermediate> > subSource, TSource item, ObservableSelectMany <TSource, TIntermediate, TResult> parent)
 {
     SubSource = subSource;
     Item      = item;
     Parent    = parent;
 }
Exemple #17
0
 public ValueTask <TResult> InvokeAsync(TSource item, CancellationToken cancellationToken)
 => selector.InvokeAsync(item, 0, cancellationToken);
Exemple #18
0
            //---------------------------------------------------------------------------------------
            // Straightforward IEnumerator<T> methods.
            //

            internal override bool MoveNext([MaybeNullWhen(false), AllowNull] ref TSource currentElement, ref int currentKey)
            {
                Debug.Assert(_source != null);

                if (_alreadySearched)
                {
                    return(false);
                }

                // Look for the lowest element.
                TSource candidate    = default(TSource) !;
                TKey    candidateKey = default(TKey) !;

                try
                {
                    TSource value = default(TSource) !;
                    TKey    key   = default(TKey) !;
                    int     i     = 0;
                    while (_source.MoveNext(ref value !, ref key))
                    {
                        if ((i++ & CancellationState.POLL_INTERVAL) == 0)
                        {
                            _cancellationToken.ThrowIfCancellationRequested();
                        }

                        // If the predicate is null or the current element satisfies it, we have found the
                        // current partition's "candidate" for the first element.  Note it.
                        if (_predicate == null || _predicate(value))
                        {
                            candidate    = value;
                            candidateKey = key;

                            lock (_operatorState)
                            {
                                if (_operatorState._partitionId == -1 || _keyComparer.Compare(candidateKey, _operatorState._key) < 0)
                                {
                                    _operatorState._key         = candidateKey;
                                    _operatorState._partitionId = _partitionId;
                                }
                            }

                            break;
                        }
                    }
                }
                finally
                {
                    if (!ParallelEnumerable.SinglePartitionMode)
                    {
                        // No matter whether we exit due to an exception or normal completion, we must ensure
                        // that we signal other partitions that we have completed.  Otherwise, we can cause deadlocks.
                        _sharedBarrier.Signal();
                    }
                }

                _alreadySearched = true;

                // Wait only if we may have the result
                if (_partitionId == _operatorState._partitionId)
                {
                    if (!ParallelEnumerable.SinglePartitionMode)
                    {
                        _sharedBarrier.Wait(_cancellationToken);
                    }

                    // Now re-read the shared index. If it's the same as ours, we won and return true.
                    if (_partitionId == _operatorState._partitionId)
                    {
                        currentElement = candidate;
                        currentKey     = 0; // 1st (and only) element, so we hardcode the output index to 0.
                        return(true);
                    }
                }

                // If we got here, we didn't win. Return false.
                return(false);
            }
 protected override TSource SafeOnNext(TSource value)
 {
     this.action(value);
     return(value);
 }
Exemple #20
0
 public SingleBase(IObservable <TSource> source, TSource value, bool append)
 {
     _source = source;
     _value  = value;
     _append = append;
 }
Exemple #21
0
 public SourceResultPair(TSource source, TResult result)
 {
     Source = source;
     Result = result;
 }
Exemple #22
0
 public SingleValue(IObservable <TSource> source, TSource value, IScheduler scheduler, bool append)
     : base(source, value, append)
 {
     Scheduler = scheduler;
 }
Exemple #23
0
 public TransformedItemContainer(TKey key, TSource source, TDestination destination)
 {
     Key         = key;
     Source      = source;
     Destination = destination;
 }
Exemple #24
0
 public SourceInfo(TSource source, Range <DateTimeOffset> range)
 {
     Source = source;
     Range  = range;
 }
Exemple #25
0
 public abstract void OnNext(TSource value);
Exemple #26
0
 public ChunkItem(TSource value)
 {
     Value = value;
 }
Exemple #27
0
            public void OnNext(TSource value)
            {
                var key = default(TKey);

                try
                {
                    key = _parent._keySelector(value);
                }
                catch (Exception exception)
                {
                    Error(exception);
                    return;
                }

                var fireNewMapEntry = false;
                var writer          = default(ISubject <TElement>);

                try
                {
                    //
                    // Note: The box instruction in the IL will be erased by the JIT in case T is
                    //       a value type. In fact, the whole if block will go away and we'll end
                    //       up with nothing but the TryGetValue check below.
                    //
                    //       // var fireNewMapEntry = false;
                    //       C:\Projects\Rx\Rx\Experimental\Main\Source\Rx\System.Reactive.Linq\Reactive\Linq\Observable\GroupBy.cs @ 67:
                    //       000007fb`6d544b80 48c7452800000000 mov     qword ptr [rbp+28h],0
                    //
                    //       // var writer = default(ISubject<TElement>);
                    //       C:\Projects\Rx\Rx\Experimental\Main\Source\Rx\System.Reactive.Linq\Reactive\Linq\Observable\GroupBy.cs @ 66:
                    //       000007fb`6d544b88 c6453400        mov     byte ptr [rbp+34h],0
                    //
                    //       // if (!_map.TryGetValue(key, out writer))
                    //       C:\Projects\Rx\Rx\Experimental\Main\Source\Rx\System.Reactive.Linq\Reactive\Linq\Observable\GroupBy.cs @ 86:
                    //       000007fb`6d544b8c 488b4560        mov     rax,qword ptr [rbp+60h]
                    //       ...
                    //
                    if (key == null)
                    {
                        if (_null == null)
                        {
                            _null           = new Subject <TElement>();
                            fireNewMapEntry = true;
                        }

                        writer = _null;
                    }
                    else
                    {
                        if (!_map.TryGetValue(key, out writer))
                        {
                            writer = new Subject <TElement>();
                            _map.Add(key, writer);
                            fireNewMapEntry = true;
                        }
                    }
                }
                catch (Exception exception)
                {
                    Error(exception);
                    return;
                }

                if (fireNewMapEntry)
                {
                    var group = new GroupedObservable <TKey, TElement>(key, writer, _parent._refCountDisposable);
                    _observer.OnNext(group);
                }

                var element = default(TElement);

                try
                {
                    element = _parent._elementSelector(value);
                }
                catch (Exception exception)
                {
                    Error(exception);
                    return;
                }

                writer.OnNext(element);
            }
Exemple #28
0
 public ManySelectorFunc(TSource source, Func <TSource, IEnumerable <TDestination> > selector)
 {
     _source   = source;
     _selector = selector ?? throw new ArgumentNullException(nameof(selector));
 }
Exemple #29
0
            public override void OnNext(TSource value)
            {
                var key = default(TKey);

                try
                {
                    key = parent.keySelector(value);
                }
                catch (Exception exception)
                {
                    Error(exception);
                    return;
                }

                var fireNewMapEntry = false;
                var writer          = default(ISubject <TElement>);

                try
                {
                    if (key == null)
                    {
                        if (nullKeySubject == null)
                        {
                            nullKeySubject  = new Subject <TElement>();
                            fireNewMapEntry = true;
                        }

                        writer = nullKeySubject;
                    }
                    else
                    {
                        if (!map.TryGetValue(key, out writer))
                        {
                            writer = new Subject <TElement>();
                            map.Add(key, writer);
                            fireNewMapEntry = true;
                        }
                    }
                }
                catch (Exception exception)
                {
                    Error(exception);
                    return;
                }

                if (fireNewMapEntry)
                {
                    var group = new GroupedObservable <TKey, TElement>(key, writer, refCountDisposable);
                    observer.OnNext(group);
                }

                var element = default(TElement);

                try
                {
                    element = parent.elementSelector(value);
                }
                catch (Exception exception)
                {
                    Error(exception);
                    return;
                }

                writer.OnNext(element);
            }
Exemple #30
0
 public void OnItem(TSource item)
 {
     Downstream.OnItem(Func(item));
 }
Exemple #31
0
 private void AddChildrenRecursively(KeyedTreeNode <TKey, IElementsProvider <TSource, TData> > pattern, TSource element)
 {
     foreach (var child in pattern.Children)
     {
         AddValuesRecursively(child, element);
     }
 }