Don't get IVsRunningDocumentTable on background thread

The `VisualStudioEditorDocumentManager` listens for running document
table events and was retrieving the `IVsRunningDocumentTable` in its
constructor. Because this is an `[ImportingConstructor]` it will
almost certain be called on the thread pool and will implicitly
marshal to the UI thread to perform a QI as part of retrieving the
service. This can cause a hang if the UI thread is tied up with other
work, such as when a solution is loaded.

This change avoids retrieving the running doc table service until its
needed and we are already running on the UI thread.
This commit is contained in:
Dustin Campbell 2024-03-26 10:27:50 -07:00
Родитель cd71979cc4
Коммит 18e4175ac5
1 изменённых файлов: 6 добавлений и 1 удалений

Просмотреть файл

@ -4,6 +4,7 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Runtime.InteropServices;
using Microsoft.AspNetCore.Razor;
@ -28,11 +29,12 @@ internal sealed class VisualStudioEditorDocumentManager(
ProjectSnapshotManagerDispatcher dispatcher,
JoinableTaskContext joinableTaskContext) : EditorDocumentManager(fileChangeTrackerFactory, dispatcher, joinableTaskContext)
{
private readonly IVsRunningDocumentTable4 _runningDocumentTable = serviceProvider.GetService<SVsRunningDocumentTable, IVsRunningDocumentTable4>(throwOnFailure: true).AssumeNotNull();
private readonly IServiceProvider _serviceProvider = serviceProvider;
private readonly IVsEditorAdaptersFactoryService _editorAdaptersFactory = editorAdaptersFactory;
private readonly Dictionary<uint, List<DocumentKey>> _documentsByCookie = [];
private readonly Dictionary<DocumentKey, uint> _cookiesByDocument = [];
private IVsRunningDocumentTable4? _runningDocumentTable;
private bool _advised;
protected override ITextBuffer? GetTextBufferForOpenDocument(string filePath)
@ -219,10 +221,13 @@ internal sealed class VisualStudioEditorDocumentManager(
}
}
[MemberNotNull(nameof(_runningDocumentTable))]
private void EnsureDocumentTableAdvised()
{
JoinableTaskContext.AssertUIThread();
_runningDocumentTable ??= _serviceProvider.GetService<SVsRunningDocumentTable, IVsRunningDocumentTable4>(throwOnFailure: true).AssumeNotNull();
if (!_advised)
{
_advised = true;