提交 67f30ecd 编写于 作者: J Jason Malinowski

Cleanup the fetching of IVsFileChangeEx for the FileChangeWatcherProvider

The FileChangeWatcherProvider has to do some magic so we can hand
out a FileChangeWatcher that fetches the IVsFileChangeEx from the shell,
but not in a way that implicitly risks any marshal back to the UI thread
in a way that might deadlock. The odd bit was we were doing some of
that initialization in the VisualStudioWorkspace constructor itself
which didn't really make sense.

While I'm here, we can also remove the hack that was working around
a shell bug where we might deadlock if we called into the async service
provider from a background thread.
上级 9e2e5bdb
using System;
using System.ComponentModel.Composition;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.Editor.Shared.Utilities;
using Microsoft.VisualStudio.Shell;
using Microsoft.VisualStudio.Shell.Interop;
namespace Microsoft.VisualStudio.LanguageServices.Implementation.ProjectSystem
......@@ -9,18 +11,23 @@ namespace Microsoft.VisualStudio.LanguageServices.Implementation.ProjectSystem
internal sealed class FileChangeWatcherProvider
{
private readonly TaskCompletionSource<IVsFileChangeEx> _fileChangeService = new TaskCompletionSource<IVsFileChangeEx>(TaskCreationOptions.RunContinuationsAsynchronously);
private readonly Lazy<FileChangeWatcher> _fileChangeWatcher;
public FileChangeWatcherProvider()
[ImportingConstructor]
public FileChangeWatcherProvider(IThreadingContext threadingContext, [Import(typeof(SVsServiceProvider))] Shell.IAsyncServiceProvider serviceProvider)
{
_fileChangeWatcher = new Lazy<FileChangeWatcher>(() => new FileChangeWatcher(_fileChangeService.Task));
}
// We do not want background work to implicitly block on the availability of the SVsFileChangeEx to avoid any deadlock risk,
// since the first fetch for a file watcher might end up happening on the background.
Watcher = new FileChangeWatcher(_fileChangeService.Task);
public FileChangeWatcher Watcher => _fileChangeWatcher.Value;
System.Threading.Tasks.Task.Run(async () =>
{
await threadingContext.JoinableTaskFactory.SwitchToMainThreadAsync();
internal void SetFileChangeService(IVsFileChangeEx fileChangeService)
{
_fileChangeService.TrySetResult(fileChangeService);
var fileChangeService = (IVsFileChangeEx)await serviceProvider.GetServiceAsync(typeof(SVsFileChangeEx)).ConfigureAwait(true);
_fileChangeService.SetResult(fileChangeService);
});
}
public FileChangeWatcher Watcher { get; }
}
}
......@@ -96,16 +96,7 @@ public VisualStudioWorkspaceImpl(ExportProvider exportProvider, IAsyncServicePro
System.Threading.Tasks.Task.Run(() => ConnectToOpenFileTrackerOnUIThreadAsync(asyncServiceProvider));
var fileChangeWatcherProvider = exportProvider.GetExportedValue<FileChangeWatcherProvider>();
FileChangeWatcher = fileChangeWatcherProvider.Watcher;
System.Threading.Tasks.Task.Run(async () =>
{
await _threadingContext.JoinableTaskFactory.SwitchToMainThreadAsync();
var fileChangeService = (IVsFileChangeEx)ServiceProvider.GlobalProvider.GetService(typeof(SVsFileChangeEx));
fileChangeWatcherProvider.SetFileChangeService(fileChangeService);
});
FileChangeWatcher = exportProvider.GetExportedValue<FileChangeWatcherProvider>().Watcher;
}
public async System.Threading.Tasks.Task ConnectToOpenFileTrackerOnUIThreadAsync(IAsyncServiceProvider asyncServiceProvider)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册