Repository: dotnet/roslyn
File: src/Features/Core/Portable/NavigateTo/INavigateToSearcherHost.cs (C#)

Code before:
    }

    /// <summary>
    /// If we're in a solution that is using OOP, this kicks off a task to get the oop side in
    /// sync with us.  Until that happens, we'll continue to use the cached results from prior
    /// sessions so that we can get results very quickly right after launch without forcing the
    /// user to wait for OOP to hydrate the entire solution over.  This strikes a good balance
    /// of speed and accuracy as most of the time cached results will be fast and good enough,
    /// and eventually (usually within dozens of seconds, even for large projects) we will
    /// switch over to full and accurate results which can also come back quickly.
    /// </summary>
    /// <remarks>
    /// If we do report cached data, we inform the user of this so they know the results may be
    /// incomplete or inaccurate and that they can try again later if necessary.
    /// </remarks>
#pragma warning disable VSTHRD200 // Use "Async" suffix for async methods
    private Task GetRemoteHostHydrateTask()
#pragma warning restore VSTHRD200 // Use "Async" suffix for async methods
    {
        lock (s_gate)
        {
            // Only need to do this once.
            if (s_remoteHostHydrateTask == null)
            {
                // If there are no projects in this solution that use OOP, then there's nothing we need to do.
                if (_solution.Projects.All(p => !RemoteSupportedLanguages.IsSupported(p.Language) || !RemoteHostClient.SupportsRemoteHostClient(_solution.Services, out var _)))
                {
                    s_remoteHostHydrateTask = Task.CompletedTask;
                }
                else
                {
                    var asyncToken = _asyncListener.BeginAsyncOperation(nameof(GetRemoteHostHydrateTask));

                    s_remoteHostHydrateTask = Task.Run(async () =>
                    {
                        var client = await RemoteHostClient.TryGetClientAsync(_solution.Services, _disposalToken).ConfigureAwait(false);
                        if (client != null)
                        {
                            await client.TryInvokeAsync<IRemoteNavigateToSearchService>(
                                _solution,
                                (service, solutionInfo, cancellationToken) =>
                                service.HydrateAsync(solutionInfo, cancellationToken),
                                _disposalToken).ConfigureAwait(false);
                        }
                    }, _disposalToken);
                    s_remoteHostHydrateTask.CompletesAsyncOperation(asyncToken);
                }
            }

            return s_remoteHostHydrateTask;
        }

Review comment (performance):
The caller checks if the s_remoteHostHydrateTask task is completed to see if solution loading is done.  Before this change the first call creates a fire and forget task below, causing IsCompleted to always be false on the first call (leading navto to think sln loading is not done and try to use cached values)

OOP is not supported outside of VS, so we can check that upfront instead and return a completed task.

Code after:
    }

    /// <summary>
    /// If we're in a solution that is using OOP, this kicks off a task to get the oop side in
    /// sync with us.  Until that happens, we'll continue to use the cached results from prior
    /// sessions so that we can get results very quickly right after launch without forcing the
    /// user to wait for OOP to hydrate the entire solution over.  This strikes a good balance
    /// of speed and accuracy as most of the time cached results will be fast and good enough,
    /// and eventually (usually within dozens of seconds, even for large projects) we will
    /// switch over to full and accurate results which can also come back quickly.
    /// </summary>
    /// <remarks>
    /// If we do report cached data, we inform the user of this so they know the results may be
    /// incomplete or inaccurate and that they can try again later if necessary.
    /// </remarks>
#pragma warning disable VSTHRD200 // Use "Async" suffix for async methods
    private Task GetRemoteHostHydrateTask()
#pragma warning restore VSTHRD200 // Use "Async" suffix for async methods
    {
        lock (s_gate)
        {
            // Only need to do this once.
            if (s_remoteHostHydrateTask == null)
            {
                // If there are no projects in this solution that use OOP, then there's nothing we need to do.
                if (_solution.Projects.All(p => !RemoteSupportedLanguages.IsSupported(p.Language)))
                {
                    s_remoteHostHydrateTask = Task.CompletedTask;
                }
                else
                {
                    var asyncToken = _asyncListener.BeginAsyncOperation(nameof(GetRemoteHostHydrateTask));

                    s_remoteHostHydrateTask = Task.Run(async () =>
                    {
                        var client = await RemoteHostClient.TryGetClientAsync(_solution.Services, _disposalToken).ConfigureAwait(false);
                        if (client != null)
                        {
                            await client.TryInvokeAsync<IRemoteNavigateToSearchService>(
                                _solution,
                                (service, solutionInfo, cancellationToken) =>
                                service.HydrateAsync(solutionInfo, cancellationToken),
                                _disposalToken).ConfigureAwait(false);
                        }
                    }, _disposalToken);
                    s_remoteHostHydrateTask.CompletesAsyncOperation(asyncToken);
                }
            }

            return s_remoteHostHydrateTask;
        }