diff --git a/src/VisualStudio/LiveShare/Impl/Client/RemoteLanguageServiceWorkspace.cs b/src/VisualStudio/LiveShare/Impl/Client/RemoteLanguageServiceWorkspace.cs index 40bbe2248f886db434739aea4faa017fbd1733d7..a2207e68316350c9c49868fe2c9cdd8c381e0994 100644 --- a/src/VisualStudio/LiveShare/Impl/Client/RemoteLanguageServiceWorkspace.cs +++ b/src/VisualStudio/LiveShare/Impl/Client/RemoteLanguageServiceWorkspace.cs @@ -61,6 +61,8 @@ internal sealed class RemoteLanguageServiceWorkspace : CodeAnalysis.Workspace, I /// private ImmutableHashSet _registeredExternalPaths; + private TaskCompletionSource? _completionSource; + private readonly RemoteDiagnosticListTable _remoteDiagnosticListTable; public bool IsRemoteSession { get; private set; } @@ -115,10 +117,15 @@ public async Task SetSession(CollaborationSession session) _session = session; IsRemoteSession = true; - // Files could have been opened before the collaboration session was fully initialized. - // So get the roots and update remote paths for all open files. + // Create a task that tracks completion of the first root path update + // on start of the live share session. + _completionSource = new TaskCompletionSource(); + + // Get the initial workspace roots and update any files that have been opened. await UpdatePathsToRemoteFilesAsync().ConfigureAwait(false); + _completionSource.TrySetResult(true); + session.RemoteServicesChanged += (object sender, RemoteServicesChangedEventArgs e) => { _remoteDiagnosticListTable.UpdateWorkspaceDiagnosticsPresent(_session.RemoteServiceNames.Contains("workspaceDiagnostics")); @@ -134,12 +141,15 @@ public string GetRemoteWorkspaceRoot(string filePath) /// /// Event that gets triggered whenever the active workspace changes. If we're in a live share session /// this means that the remote workpace roots have also changed and need to be updated. + /// This will not be called concurrently. /// private async Task OnActiveWorkspaceChangedAsync(object sender, EventArgs args) { - if (IsRemoteSession) + if (IsRemoteSession && _completionSource != null) { - await UpdatePathsToRemoteFilesAsync().ConfigureAwait(false); + // It's possible (though unlikely) that a workspace changed event comes in concurrently with the collaboration session creation. + // So wait for the completion of the root update from session creation to try to update the roots. + await _completionSource.Task.ContinueWith(_ => UpdatePathsToRemoteFilesAsync(), TaskScheduler.Default).ConfigureAwait(false); } }