Пример #1
0
        // Original source from: http://codereview.stackexchange.com/questions/11377/implementation-of-a-throttled-concurrentqueue-rx-observer
        public static IObservable <T> AsRateLimitedObservable <T>(this BlockingCollection <T> sequence, int occurrences, TimeSpan timeUnit, CancellationToken cancellationToken)
        {
            var subject       = new Subject <T>();
            var token         = new CancellationToken();
            var tokenSource   = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, token);
            var consumingTask = new Task(() =>
            {
                using (var throttle = new Throttle(occurrences, timeUnit))
                {
                    while (!sequence.IsCompleted)
                    {
                        try
                        {
                            var item = sequence.Take(cancellationToken);
                            throttle.WaitToProceed();
                            try
                            {
                                subject.OnNext(item);
                            }
                            catch (Exception ex)
                            {
                                subject.OnError(ex);
                            }
                        }
                        catch (OperationCanceledException)
                        {
                            break;
                        }
                    }
                    subject.OnCompleted();
                }
            }, TaskCreationOptions.LongRunning);

            return(new TaskAwareObservable <T>(subject, consumingTask, tokenSource));
        }
    // TODO: devise a way to avoid problems if collection gets too big (produced faster than consumed)
    public static IObservable <T> AsRateLimitedObservable <T>(this BlockingCollection <T> sequence, int items, TimeSpan timePeriod, CancellationToken producerToken)
    {
        Subject <T> subject = new Subject <T>();
        // this is a dummyToken just so we can recreate the TokenSource
        // which we will pass the proxy class so it can cancel the task
        // on disposal
        CancellationToken       dummyToken  = new CancellationToken();
        CancellationTokenSource tokenSource = CancellationTokenSource.CreateLinkedTokenSource(producerToken, dummyToken);
        var consumingTask = new Task(() =>
        {
            using (var throttle = new Throttle(items, timePeriod))
            {
                while (!sequence.IsCompleted)
                {
                    try
                    {
                        T item = sequence.Take(producerToken);
                        throttle.WaitToProceed();
                        try
                        {
                            subject.OnNext(item);
                        }
                        catch (Exception ex)
                        {
                            subject.OnError(ex);
                        }
                    }
                    catch (OperationCanceledException)
                    {
                        break;
                    }
                }
                subject.OnCompleted();
            }
        }, TaskCreationOptions.LongRunning);

        return(new TaskAwareObservable <T>(subject, consumingTask, tokenSource));
    }