public async Task UpdaterService()
        {
            var exportProvider = TestHostServices.CreateMinimalExportProvider();

            using var workspace = new AdhocWorkspace(TestHostServices.CreateHostServices(exportProvider));

            var options = workspace.CurrentSolution.Options
                          .WithChangedOption(RemoteHostOptions.SolutionChecksumMonitorBackOffTimeSpanInMS, 1)
                          .WithChangedOption(RemoteTestHostOptions.RemoteHostTest, true);

            workspace.TryApplyChanges(workspace.CurrentSolution.WithOptions(options));

            var listenerProvider = exportProvider.GetExportedValue <AsynchronousOperationListenerProvider>();

            var checksumUpdater = new SolutionChecksumUpdater(workspace, listenerProvider, CancellationToken.None);
            var service         = workspace.Services.GetRequiredService <IRemoteHostClientProvider>();

            // make sure client is ready
            using var client = await service.TryGetRemoteHostClientAsync(CancellationToken.None);

            // add solution
            workspace.AddSolution(SolutionInfo.Create(SolutionId.CreateNewId(), VersionStamp.Default));

            // wait for listener
            var workspaceListener = listenerProvider.GetWaiter(FeatureAttribute.Workspace);
            await workspaceListener.ExpeditedWaitAsync();

            var listener = listenerProvider.GetWaiter(FeatureAttribute.SolutionChecksumUpdater);
            await listener.ExpeditedWaitAsync();

            // checksum should already exist
            Assert.True(workspace.CurrentSolution.State.TryGetStateChecksums(out _));

            checksumUpdater.Shutdown();
        }
        public async Task UpdaterService()
        {
            var hostServices = s_composition.GetHostServices();

            using var workspace = new AdhocWorkspace(hostServices);

            var options = workspace.CurrentSolution.Options.WithChangedOption(
                RemoteHostOptions.SolutionChecksumMonitorBackOffTimeSpanInMS,
                1
                );

            workspace.TryApplyChanges(workspace.CurrentSolution.WithOptions(options));

            var listenerProvider = (
                (IMefHostExportProvider)hostServices
                ).GetExportedValue <AsynchronousOperationListenerProvider>();

            var checksumUpdater = new SolutionChecksumUpdater(
                workspace,
                listenerProvider,
                CancellationToken.None
                );
            var service = workspace.Services.GetRequiredService <IRemoteHostClientProvider>();

            // make sure client is ready
            using var client = await service.TryGetRemoteHostClientAsync(CancellationToken.None);

            // add solution, change document
            workspace.AddSolution(
                SolutionInfo.Create(SolutionId.CreateNewId(), VersionStamp.Default)
                );
            var project  = workspace.AddProject("proj", LanguageNames.CSharp);
            var document = workspace.AddDocument(project.Id, "doc.cs", SourceText.From("code"));

            workspace.ApplyTextChanges(
                document.Id,
                new[] { new TextChange(new TextSpan(0, 1), "abc") },
                CancellationToken.None
                );

            // wait for listener
            var workspaceListener = listenerProvider.GetWaiter(FeatureAttribute.Workspace);
            await workspaceListener.ExpeditedWaitAsync();

            var listener = listenerProvider.GetWaiter(FeatureAttribute.SolutionChecksumUpdater);
            await listener.ExpeditedWaitAsync();

            // checksum should already exist
            Assert.True(workspace.CurrentSolution.State.TryGetStateChecksums(out _));

            checksumUpdater.Shutdown();
        }
        public async Task UpdaterService()
        {
            var exportProvider = ExportProviderCache
                                 .GetOrCreateExportProviderFactory(ServiceTestExportProvider.CreateAssemblyCatalog()
                                                                   .WithParts(typeof(InProcRemoteHostClientProvider.Factory), typeof(CSharpOptionsSerializationService)))
                                 .CreateExportProvider();

            using var workspace = new AdhocWorkspace(TestHostServices.CreateHostServices(exportProvider));

            var options = workspace.CurrentSolution.Options
                          .WithChangedOption(Microsoft.VisualStudio.LanguageServices.Remote.RemoteHostOptions.SolutionChecksumMonitorBackOffTimeSpanInMS, 1)
                          .WithChangedOption(Microsoft.CodeAnalysis.Test.Utilities.RemoteHost.RemoteHostOptions.RemoteHostTest, true);

            workspace.TryApplyChanges(workspace.CurrentSolution.WithOptions(options));

            var listenerProvider = exportProvider.GetExportedValue <AsynchronousOperationListenerProvider>();

            var checksumUpdater = new SolutionChecksumUpdater(workspace, listenerProvider, CancellationToken.None);
            var service         = workspace.Services.GetRequiredService <IRemoteHostClientProvider>();

            // make sure client is ready
            using var client = await service.TryGetRemoteHostClientAsync(CancellationToken.None);

            // add solution, change document
            workspace.AddSolution(SolutionInfo.Create(SolutionId.CreateNewId(), VersionStamp.Default));
            var project  = workspace.AddProject("proj", LanguageNames.CSharp);
            var document = workspace.AddDocument(project.Id, "doc.cs", SourceText.From("code"));

            workspace.ApplyTextChanges(document.Id, new[] { new TextChange(new TextSpan(0, 1), "abc") }, CancellationToken.None);

            // wait for listener
            var workspaceListener = listenerProvider.GetWaiter(FeatureAttribute.Workspace);
            await workspaceListener.ExpeditedWaitAsync();

            var listener = listenerProvider.GetWaiter(FeatureAttribute.SolutionChecksumUpdater);
            await listener.ExpeditedWaitAsync();

            // checksum should already exist
            Assert.True(workspace.CurrentSolution.State.TryGetStateChecksums(out _));

            checksumUpdater.Shutdown();
        }
            public void Enable()
            {
                lock (_gate)
                {
                    if (_instanceTask != null)
                    {
                        // already enabled
                        return;
                    }

                    // We enable the remote host if either RemoteHostTest or RemoteHost are on.
                    if (!_workspace.Options.GetOption(RemoteHostOptions.RemoteHostTest) &&
                        !_workspace.Options.GetOption(RemoteHostOptions.RemoteHost))
                    {
                        // not turned on
                        return;
                    }

                    // log that remote host is enabled
                    Logger.Log(FunctionId.RemoteHostClientService_Enabled, KeyValueLogMessage.NoProperty);

                    var remoteHostClientFactory = _workspace.Services.GetService<IRemoteHostClientFactory>();
                    if (remoteHostClientFactory == null)
                    {
                        // dev14 doesn't have remote host client factory
                        return;
                    }

                    // make sure we run it on background thread
                    _shutdownCancellationTokenSource = new CancellationTokenSource();

                    var token = _shutdownCancellationTokenSource.Token;

                    // create solution checksum updater
                    _checksumUpdater = new SolutionChecksumUpdater(this, token);

                    _instanceTask = Task.Run(() => EnableAsync(token), token);
                }
            }
            public void Disable()
            {
                lock (_gate)
                {
                    if (_instanceTask == null)
                    {
                        // already disabled
                        return;
                    }

                    var instanceTask = _instanceTask;
                    _instanceTask = null;

                    RemoveGlobalAssets();

                    _shutdownCancellationTokenSource.Cancel();

                    _checksumUpdater.Shutdown();
                    _checksumUpdater = null;

                    try
                    {
                        instanceTask.Wait(_shutdownCancellationTokenSource.Token);

                        // result can be null if service hub failed to launch
                        instanceTask.Result?.Shutdown();
                    }
                    catch (OperationCanceledException)
                    {
                        // _instance wasn't finished running yet.
                    }
                }
            }