public void ComplexScrollAllObservable()
        {
            int numberOfSlices = Environment.ProcessorCount;

            var scrollAllObservable = Client.ScrollAll <Project>("10s", numberOfSlices, sc => sc
                                                                 .MaxDegreeOfParallelism(numberOfSlices)
                                                                 .Search(s => s
                                                                         .Query(q => q
                                                                                .Term(f => f.State, StateOfBeing.Stable)
                                                                                )
                                                                         )
                                                                 );

            var waitHandle             = new ManualResetEvent(false);
            ExceptionDispatchInfo info = null;

            var scrollAllObserver = new ScrollAllObserver <Project>(
                onNext: response => ProcessResponse(response.SearchResponse),                 // <1> do something with the response
                onError: e =>
            {
                info = ExceptionDispatchInfo.Capture(e);                         // <2> if an exception is thrown, capture it to throw outside of the observer
                waitHandle.Set();
            },
                onCompleted: () => waitHandle.Set()
                );

            scrollAllObservable.Subscribe(scrollAllObserver); // <3> initiate scrolling

            waitHandle.WaitOne();                             // <4> block the current thread until the wait handle is set
            info?.Throw();                                    // <5> if an exception was captured whilst scrolling, throw it
        }
        private void ScrollAll(string index, int numberOfShards, int numberOfDocuments)
        {
            var handle           = new ManualResetEvent(false);
            var scrollObservable = this._client.ScrollAll <SmallObject>("1m", numberOfShards, s => s
                                                                        .MaxDegreeOfParallelism(numberOfShards / 2)
                                                                        .Search(search => search
                                                                                .Index(index)
                                                                                .AllTypes()
                                                                                .MatchAll()
                                                                                )
                                                                        );

            //we set up an observer
            var seenDocuments = 0;
            var seenSlices    = new ConcurrentBag <int>();

            //since we call allTypes search should be bounded to index.
            var scrollObserver = new ScrollAllObserver <SmallObject>(
                onError: (e) => { handle.Set(); throw e; },
                onCompleted: () => handle.Set(),
                onNext: (b) =>
            {
                seenSlices.Add(b.Slice);
                Interlocked.Add(ref seenDocuments, b.SearchResponse.Hits.Count);
            }
                );

            //when we subscribe the observable becomes hot
            scrollObservable.Subscribe(scrollObserver);
            handle.WaitOne(TimeSpan.FromMinutes(5));
            seenDocuments.Should().Be(numberOfDocuments);
            var groups = seenSlices.GroupBy(s => s).ToList();

            groups.Count().Should().Be(numberOfShards);
            groups.Should().OnlyContain(g => g.Count() > 1);
        }