public async Task LaunchBuildServerInfoFetchOperationAsync()
        {
            await TaskScheduler.Default;

            CancelBuildStatusFetchOperation();

            var launchToken = _launchCancellation.Next();

            var buildServerAdapter = await GetBuildServerAdapterAsync().ConfigureAwait(false);

            await _revisionGridView.SwitchToMainThreadAsync(launchToken);

            _buildServerAdapter?.Dispose();
            _buildServerAdapter = buildServerAdapter;

            await TaskScheduler.Default;

            if (buildServerAdapter == null || launchToken.IsCancellationRequested)
            {
                return;
            }

            var scheduler = NewThreadScheduler.Default;

            // Run this first as it (may) force start queries
            var runningBuildsObservable = buildServerAdapter.GetRunningBuilds(scheduler);

            var fullDayObservable = buildServerAdapter.GetFinishedBuildsSince(scheduler, DateTime.Today - TimeSpan.FromDays(3));
            var fullObservable    = buildServerAdapter.GetFinishedBuildsSince(scheduler);
            var fromNowObservable = buildServerAdapter.GetFinishedBuildsSince(scheduler, DateTime.Now);

            var isBuildRunning    = false;
            var cancellationToken = new CompositeDisposable
            {
                fullDayObservable.OnErrorResumeNext(fullObservable)
                .OnErrorResumeNext(Observable.Empty <BuildInfo>()
                                   .DelaySubscription(TimeSpan.FromMinutes(1))
                                   .OnErrorResumeNext(fromNowObservable)
                                   .Retry()
                                   .Repeat())
                .ObserveOn(MainThreadScheduler.Instance)
                .Subscribe(OnBuildInfoUpdate),

                runningBuildsObservable.Do(_ => isBuildRunning = true)
                .Finally(() =>
                {
                    Thread.Sleep(TimeSpan.FromSeconds(isBuildRunning ? PollIntervalWhenSomeBuildsAreRunning : PollIntervalWhenNoBuildsAreRunning));
                    isBuildRunning = false;
                })
                .Retry()
                .Repeat()
                .ObserveOn(MainThreadScheduler.Instance)
                .Subscribe(OnBuildInfoUpdate)
            };

            await _revisionGridView.SwitchToMainThreadAsync(launchToken);

            CancelBuildStatusFetchOperation();
            _buildStatusCancellationToken = cancellationToken;
        }
        public async Task LaunchBuildServerInfoFetchOperationAsync()
        {
            await TaskScheduler.Default;

            CancelBuildStatusFetchOperation();

            var launchToken = _launchCancellation.Next();

            var buildServerAdapter = await GetBuildServerAdapterAsync().ConfigureAwait(false);

            await _revisionGridView.SwitchToMainThreadAsync(launchToken);

            _buildServerAdapter?.Dispose();
            _buildServerAdapter = buildServerAdapter;

            await TaskScheduler.Default;

            if (buildServerAdapter == null || launchToken.IsCancellationRequested)
            {
                return;
            }

            var scheduler = NewThreadScheduler.Default;

            // Run this first as it (may) force start queries
            var runningBuildsObservable = buildServerAdapter.GetRunningBuilds(scheduler);

            var fullDayObservable = buildServerAdapter.GetFinishedBuildsSince(scheduler, DateTime.Today - TimeSpan.FromDays(3));
            var fullObservable    = buildServerAdapter.GetFinishedBuildsSince(scheduler);

            bool anyRunningBuilds = false;
            var  delayObservable  = Observable.Defer(() => Observable.Empty <BuildInfo>()
                                                     .DelaySubscription(anyRunningBuilds ? ShortPollInterval : LongPollInterval));

            var      shouldLookForNewlyFinishedBuilds = false;
            DateTime nowFrozen = DateTime.Now;

            // All finished builds have already been retrieved,
            // so looking for new finished builds make sense only if running builds have been found previously
            var fromNowObservable = Observable.If(() => shouldLookForNewlyFinishedBuilds,
                                                  buildServerAdapter.GetFinishedBuildsSince(scheduler, nowFrozen)
                                                  .Finally(() => shouldLookForNewlyFinishedBuilds = false));

            var cancellationToken = new CompositeDisposable
            {
                fullDayObservable.OnErrorResumeNext(fullObservable)
                .OnErrorResumeNext(Observable.Empty <BuildInfo>()
                                   .DelaySubscription(TimeSpan.FromMinutes(1))
                                   .OnErrorResumeNext(fromNowObservable)
                                   .Retry()
                                   .Repeat())
                .ObserveOn(MainThreadScheduler.Instance)
                .Subscribe(OnBuildInfoUpdate),

                runningBuildsObservable.Do(buildInfo =>
                {
                    anyRunningBuilds = true;
                    shouldLookForNewlyFinishedBuilds = true;
                })
                .Retry()
                .Concat(delayObservable)
                .Finally(() => anyRunningBuilds = false)
                .Repeat()
                .ObserveOn(MainThreadScheduler.Instance)
                .Subscribe(OnBuildInfoUpdate)
            };

            await _revisionGridView.SwitchToMainThreadAsync(launchToken);

            CancelBuildStatusFetchOperation();
            _buildStatusCancellationToken = cancellationToken;
        }