Skip to content
This repository was archived by the owner on Jun 21, 2023. It is now read-only.

Commit 8d37c78

Browse files
committed
Don't use SwitchToMainThreadAsync to avoid potential hang
Be explicit about which code needs the Main thread Don't auto-load in background to prevent potential SwitchToMainThreadAsync hang. SwitchToMainThreadAsync can hang so use ThreadingHelper.MainThreadDispatcher.InvokeAsync instead.
1 parent 584ebc5 commit 8d37c78

File tree

2 files changed

+25
-22
lines changed

2 files changed

+25
-22
lines changed

src/GitHub.InlineReviews/InlineReviewsPackage.cs

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,21 +2,20 @@
22
using System.ComponentModel.Design;
33
using System.Runtime.InteropServices;
44
using System.Threading;
5+
using GitHub.Helpers;
56
using GitHub.Commands;
67
using GitHub.InlineReviews.Views;
78
using GitHub.Services.Vssdk.Commands;
89
using GitHub.VisualStudio;
910
using Microsoft.VisualStudio.ComponentModelHost;
1011
using Microsoft.VisualStudio.Shell;
11-
using Microsoft.VisualStudio.Shell.Interop;
1212
using Task = System.Threading.Tasks.Task;
1313

1414
namespace GitHub.InlineReviews
1515
{
16-
// Initialize menus on Main thread.
17-
[PackageRegistration(UseManagedResourcesOnly = true, AllowsBackgroundLoading = false)]
16+
[PackageRegistration(UseManagedResourcesOnly = true, AllowsBackgroundLoading = true)]
1817
[Guid(Guids.InlineReviewsPackageId)]
19-
[ProvideAutoLoad(Guids.UIContext_Git)]
18+
[ProvideAutoLoad(Guids.UIContext_Git, PackageAutoLoadFlags.BackgroundLoad)]
2019
[ProvideMenuResource("Menus.ctmenu", 1)]
2120
[ProvideToolWindow(typeof(PullRequestCommentsPane), DocumentLikeTool = true)]
2221
public class InlineReviewsPackage : AsyncPackage
@@ -27,11 +26,14 @@ protected override async Task InitializeAsync(
2726
{
2827
var menuService = (IMenuCommandService)(await GetServiceAsync(typeof(IMenuCommandService)));
2928
var componentModel = (IComponentModel)(await GetServiceAsync(typeof(SComponentModel)));
30-
3129
var exports = componentModel.DefaultExportProvider;
32-
menuService.AddCommands(
33-
exports.GetExportedValue<INextInlineCommentCommand>(),
34-
exports.GetExportedValue<IPreviousInlineCommentCommand>());
30+
31+
// await ThreadingHelper.SwitchToMainThreadAsync() won't return until after a solution
32+
// has been loaded. We're using the following instead as a workaround.
33+
await ThreadingHelper.MainThreadDispatcher.InvokeAsync(() =>
34+
menuService.AddCommands(
35+
exports.GetExportedValue<INextInlineCommentCommand>(),
36+
exports.GetExportedValue<IPreviousInlineCommentCommand>()));
3537
}
3638
}
3739
}

src/GitHub.VisualStudio/GitHubPackage.cs

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,11 @@
2424

2525
namespace GitHub.VisualStudio
2626
{
27-
// Initialize menus on Main thread.
28-
[PackageRegistration(UseManagedResourcesOnly = true, AllowsBackgroundLoading = false)]
27+
[PackageRegistration(UseManagedResourcesOnly = true, AllowsBackgroundLoading = true)]
2928
[InstalledProductRegistration("#110", "#112", AssemblyVersionInformation.Version, IconResourceID = 400)]
3029
[Guid(Guids.guidGitHubPkgString)]
3130
[ProvideMenuResource("Menus.ctmenu", 1)]
32-
// Only initialize when we're in the context of a Git repository.
33-
[ProvideAutoLoad(Guids.UIContext_Git)]
31+
[ProvideAutoLoad(Guids.UIContext_Git, PackageAutoLoadFlags.BackgroundLoad)]
3432
[ProvideToolWindow(typeof(GitHubPane), Orientation = ToolWindowOrientation.Right, Style = VsDockStyle.Tabbed, Window = EnvDTE.Constants.vsWindowKindSolutionExplorer)]
3533
[ProvideOptionPage(typeof(OptionsPage), "GitHub for Visual Studio", "General", 0, 0, supportsAutomation: true)]
3634
public class GitHubPackage : AsyncPackage
@@ -71,17 +69,20 @@ async Task InitializeMenus()
7169
{
7270
var menuService = (IMenuCommandService)(await GetServiceAsync(typeof(IMenuCommandService)));
7371
var componentModel = (IComponentModel)(await GetServiceAsync(typeof(SComponentModel)));
74-
7572
var exports = componentModel.DefaultExportProvider;
76-
menuService.AddCommands(
77-
exports.GetExportedValue<IAddConnectionCommand>(),
78-
exports.GetExportedValue<IBlameLinkCommand>(),
79-
exports.GetExportedValue<ICopyLinkCommand>(),
80-
exports.GetExportedValue<ICreateGistCommand>(),
81-
exports.GetExportedValue<IOpenLinkCommand>(),
82-
exports.GetExportedValue<IOpenPullRequestsCommand>(),
83-
exports.GetExportedValue<IShowCurrentPullRequestCommand>(),
84-
exports.GetExportedValue<IShowGitHubPaneCommand>());
73+
74+
// await ThreadingHelper.SwitchToMainThreadAsync() won't return until after a solution
75+
// has been loaded. We're using the following instead as a workaround.
76+
await ThreadingHelper.MainThreadDispatcher.InvokeAsync(() =>
77+
menuService.AddCommands(
78+
exports.GetExportedValue<IAddConnectionCommand>(),
79+
exports.GetExportedValue<IBlameLinkCommand>(),
80+
exports.GetExportedValue<ICopyLinkCommand>(),
81+
exports.GetExportedValue<ICreateGistCommand>(),
82+
exports.GetExportedValue<IOpenLinkCommand>(),
83+
exports.GetExportedValue<IOpenPullRequestsCommand>(),
84+
exports.GetExportedValue<IShowCurrentPullRequestCommand>(),
85+
exports.GetExportedValue<IShowGitHubPaneCommand>()));
8586
}
8687

8788
async Task EnsurePackageLoaded(Guid packageGuid)

0 commit comments

Comments
 (0)