Skip to content

Commit 0ddeab5

Browse files
author
Paul van Brenk
committed
Fix threading issue output window
1 parent 65a5659 commit 0ddeab5

File tree

3 files changed

+30
-50
lines changed

3 files changed

+30
-50
lines changed

Nodejs/Product/Nodejs/SharedProject/OutputWindowWrapper.cs

Lines changed: 28 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -24,41 +24,37 @@ public sealed class OutputPaneWrapper
2424
private SVsServiceProvider ServiceProvider { get; set; }
2525

2626
private Dictionary<OutputWindowTarget, IVsOutputWindowPane> lazyOutputPaneCollection = new Dictionary<OutputWindowTarget, IVsOutputWindowPane>();
27-
private IVsWindowFrame lazyOutputWindow;
2827

29-
private IVsOutputWindowPane GetOutputPane(OutputWindowTarget target)
28+
public OutputPaneWrapper()
3029
{
31-
if (this.lazyOutputPaneCollection.TryGetValue(target, out var lazyOutputPane))
32-
{
33-
return lazyOutputPane;
34-
}
35-
else
36-
{
37-
ThreadHelper.ThrowIfNotOnUIThread();
38-
var (title, guid) = GetPaneInfo(target);
39-
var outputWindow = (IVsOutputWindow)this.ServiceProvider.GetService(typeof(SVsOutputWindow));
30+
//...
31+
}
4032

41-
// Try to get the workspace pane if it has already been registered
42-
var hr = outputWindow.GetPane(guid, out lazyOutputPane);
33+
private void InitializeOutputPane(OutputWindowTarget target)
34+
{
35+
ThreadHelper.ThrowIfNotOnUIThread();
36+
var (title, guid) = GetPaneInfo(target);
37+
var outputWindow = (IVsOutputWindow)this.ServiceProvider.GetService(typeof(SVsOutputWindow));
4338

44-
// If the workspace pane has not been registered before, create it
45-
if (lazyOutputPane == null || ErrorHandler.Failed(hr))
46-
{
39+
// Try to get the workspace pane if it has already been registered
40+
var hr = outputWindow.GetPane(guid, out var lazyOutputPane);
4741

48-
if (ErrorHandler.Failed(outputWindow.CreatePane(guid, title, fInitVisible: 1, fClearWithSolution: 1)) ||
49-
ErrorHandler.Failed(outputWindow.GetPane(guid, out lazyOutputPane)))
50-
{
51-
return null;
52-
}
42+
// If the workspace pane has not been registered before, create it
43+
if (lazyOutputPane == null || ErrorHandler.Failed(hr))
44+
{
5345

54-
// Must activate the workspace pane for it to show up in the output window
55-
lazyOutputPane.Activate();
46+
if (ErrorHandler.Failed(outputWindow.CreatePane(guid, title, fInitVisible: 1, fClearWithSolution: 1)) ||
47+
ErrorHandler.Failed(outputWindow.GetPane(guid, out lazyOutputPane)))
48+
{
49+
return;
5650
}
5751

58-
this.lazyOutputPaneCollection.Add(target, lazyOutputPane);
59-
return lazyOutputPane;
52+
// Must activate the workspace pane for it to show up in the output window
53+
lazyOutputPane.Activate();
6054
}
6155

56+
this.lazyOutputPaneCollection.Add(target, lazyOutputPane);
57+
6258
(string title, Guid guid) GetPaneInfo(OutputWindowTarget pane)
6359
{
6460
switch (pane)
@@ -73,39 +69,23 @@ private IVsOutputWindowPane GetOutputPane(OutputWindowTarget target)
7369
}
7470
}
7571

76-
private IVsWindowFrame OutputWindow
77-
{
78-
get
79-
{
80-
if (this.lazyOutputWindow == null && this.ServiceProvider.GetService(typeof(SVsUIShell)) is IVsUIShell shell)
81-
{
82-
ThreadHelper.ThrowIfNotOnUIThread();
83-
84-
var windowGuid = OutputWindowGuid;
85-
var hr = shell.FindToolWindow((int)__VSFINDTOOLWIN.FTW_fForceCreate, ref windowGuid, out this.lazyOutputWindow);
86-
Debug.Assert(ErrorHandler.Succeeded(hr));
87-
}
88-
89-
return this.lazyOutputWindow;
90-
}
91-
}
92-
9372
public void WriteLine(string message, OutputWindowTarget target = OutputWindowTarget.Npm)
9473
{
95-
if (this.lazyOutputWindow == null)
74+
if (!this.lazyOutputPaneCollection.TryGetValue(target, out var lazyOutputPane))
9675
{
97-
throw new InvalidOperationException($"Ensure the output window is initialized by calling '{nameof(ShowWindow)}' first.");
76+
throw new InvalidOperationException("You need to initialize the output panes before using them.");
9877
}
9978

100-
var hr = this.GetOutputPane(target).OutputStringThreadSafe(message + Environment.NewLine);
79+
var hr = lazyOutputPane.OutputStringThreadSafe(message + Environment.NewLine);
10180
Debug.Assert(ErrorHandler.Succeeded(hr));
10281
}
10382

104-
public void ShowWindow()
83+
public void InitializeOutputPanes()
10584
{
10685
ThreadHelper.ThrowIfNotOnUIThread();
107-
var hr = this.OutputWindow?.ShowNoActivate() ?? VSConstants.E_FAIL;
108-
Debug.Assert(ErrorHandler.Succeeded(hr));
86+
87+
InitializeOutputPane(OutputWindowTarget.Npm);
88+
InitializeOutputPane(OutputWindowTarget.Tsc);
10989
}
11090
}
11191

Nodejs/Product/Nodejs/Workspace/ContextMenuProvider.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ public int Exec(List<WorkspaceVisualNodeBase> selection, Guid pguidCmdGroup, uin
7575

7676
if (pguidCmdGroup == Guids.NodeToolsWorkspaceCmdSet)
7777
{
78-
this.outputPane.ShowWindow();
78+
this.outputPane.InitializeOutputPanes();
7979

8080
switch (nCmdID)
8181
{

Nodejs/Product/Nodejs/Workspace/TypeScriptActionProviderFactory.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ public async Task<IReadOnlyList<IFileContextAction>> GetActionsAsync(string file
6060
{
6161
await this.workspaceContext.JTF.SwitchToMainThreadAsync();
6262

63-
this.outputPane.ShowWindow();
63+
this.outputPane.InitializeOutputPanes();
6464

6565
var actions = new List<IFileContextAction>();
6666

0 commit comments

Comments
 (0)