From 8aa4e0ac2bdf1f7b185753eca0f1f7b4bc5c05c1 Mon Sep 17 00:00:00 2001 From: David Wengier Date: Mon, 21 Mar 2022 09:09:21 +1100 Subject: [PATCH] Don't block on clearing the output window on the UI thread when generating a file (#60281) --- .../IPdbSourceDocumentLogger.cs | 2 +- ...urceDocumentMetadataAsSourceFileProvider.cs | 9 ++------- .../PdbSourceDocumentOutputWindowLogger.cs | 18 ++++++++++-------- 3 files changed, 13 insertions(+), 16 deletions(-) diff --git a/src/Features/Core/Portable/PdbSourceDocument/IPdbSourceDocumentLogger.cs b/src/Features/Core/Portable/PdbSourceDocument/IPdbSourceDocumentLogger.cs index f29569eb36f25..03cdd54f3baee 100644 --- a/src/Features/Core/Portable/PdbSourceDocument/IPdbSourceDocumentLogger.cs +++ b/src/Features/Core/Portable/PdbSourceDocument/IPdbSourceDocumentLogger.cs @@ -12,7 +12,7 @@ namespace Microsoft.CodeAnalysis.PdbSourceDocument /// internal interface IPdbSourceDocumentLogger { - Task ClearAsync(); + void Clear(); void Log(string message); } diff --git a/src/Features/Core/Portable/PdbSourceDocument/PdbSourceDocumentMetadataAsSourceFileProvider.cs b/src/Features/Core/Portable/PdbSourceDocument/PdbSourceDocumentMetadataAsSourceFileProvider.cs index fee7d42220e2c..a359f330eea38 100644 --- a/src/Features/Core/Portable/PdbSourceDocument/PdbSourceDocumentMetadataAsSourceFileProvider.cs +++ b/src/Features/Core/Portable/PdbSourceDocument/PdbSourceDocumentMetadataAsSourceFileProvider.cs @@ -60,13 +60,8 @@ internal sealed class PdbSourceDocumentMetadataAsSourceFileProvider : IMetadataA var assemblyName = symbol.ContainingAssembly.Identity.Name; var assemblyVersion = symbol.ContainingAssembly.Identity.Version.ToString(); - if (_logger is not null) - { - // We block to clear the log from the previous operation, so things don't get confusing - // if the log messages are delayed - await _logger.ClearAsync().ConfigureAwait(false); - } - + // Clear the log so messages from the previously generated file don't confuse the user + _logger?.Clear(); _logger?.Log(FeaturesResources.Navigating_to_symbol_0_from_1, symbol, assemblyName); var compilation = await project.GetRequiredCompilationAsync(cancellationToken).ConfigureAwait(false); diff --git a/src/VisualStudio/Core/Def/PdbSourceDocument/PdbSourceDocumentOutputWindowLogger.cs b/src/VisualStudio/Core/Def/PdbSourceDocument/PdbSourceDocumentOutputWindowLogger.cs index b5e020e435942..f690746ef9ce5 100644 --- a/src/VisualStudio/Core/Def/PdbSourceDocument/PdbSourceDocumentOutputWindowLogger.cs +++ b/src/VisualStudio/Core/Def/PdbSourceDocument/PdbSourceDocumentOutputWindowLogger.cs @@ -27,7 +27,7 @@ internal sealed class PdbSourceDocumentOutputWindowLogger : IPdbSourceDocumentLo private IVsOutputWindowPane? _outputPane; private readonly IThreadingContext _threadingContext; - private readonly AsyncBatchingWorkQueue _logItemsQueue; + private readonly AsyncBatchingWorkQueue _logItemsQueue; private readonly IServiceProvider _serviceProvider; private readonly CancellationTokenSource _cancellationTokenSource = new(); @@ -41,14 +41,14 @@ public PdbSourceDocumentOutputWindowLogger(SVsServiceProvider serviceProvider, I var asyncListener = listenerProvider.GetListener(nameof(PdbSourceDocumentOutputWindowLogger)); - _logItemsQueue = new AsyncBatchingWorkQueue( + _logItemsQueue = new AsyncBatchingWorkQueue( DelayTimeSpan.NearImmediate, ProcessLogMessagesAsync, asyncListener, _cancellationTokenSource.Token); } - private async ValueTask ProcessLogMessagesAsync(ImmutableArray messages, CancellationToken cancellationToken) + private async ValueTask ProcessLogMessagesAsync(ImmutableArray messages, CancellationToken cancellationToken) { await _threadingContext.JoinableTaskFactory.SwitchToMainThreadAsync(cancellationToken); @@ -60,7 +60,11 @@ private async ValueTask ProcessLogMessagesAsync(ImmutableArray messages, return; } - if (pane is IVsOutputWindowPaneNoPump noPumpPane) + if (message is null) + { + pane.Clear(); + } + else if (pane is IVsOutputWindowPaneNoPump noPumpPane) { noPumpPane.OutputStringNoPump(message + Environment.NewLine); } @@ -71,11 +75,9 @@ private async ValueTask ProcessLogMessagesAsync(ImmutableArray messages, } } - public async Task ClearAsync() + public void Clear() { - await _threadingContext.JoinableTaskFactory.SwitchToMainThreadAsync(); - - GetPane()?.Clear(); + _logItemsQueue.AddWork((string?)null); } public void Log(string value)