From 8bf1864ffa8fffde153f8fcc1a70d73514dffe46 Mon Sep 17 00:00:00 2001 From: Jamie Cansdale Date: Fri, 11 Jan 2019 12:54:40 +0000 Subject: [PATCH 1/2] Marshal OnStartSearch onto UI thread OnStartSearch is called on a background thread. Marshal onto UI thread when updating view model. --- src/GitHub.VisualStudio/UI/GitHubPane.cs | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/src/GitHub.VisualStudio/UI/GitHubPane.cs b/src/GitHub.VisualStudio/UI/GitHubPane.cs index 461761a8f5..2ab888224a 100644 --- a/src/GitHub.VisualStudio/UI/GitHubPane.cs +++ b/src/GitHub.VisualStudio/UI/GitHubPane.cs @@ -82,7 +82,9 @@ protected override void Initialize() // Using JoinableTaskFactory from parent AsyncPackage. That way if VS shuts down before this // work is done, we won't risk crashing due to arbitrary work going on in background threads. var asyncPackage = (AsyncPackage)Package; - viewModelTask = asyncPackage.JoinableTaskFactory.RunAsync(() => InitializeAsync(asyncPackage)); + JoinableTaskFactory = asyncPackage.JoinableTaskFactory; + + viewModelTask = JoinableTaskFactory.RunAsync(() => InitializeAsync(asyncPackage)); } public Task GetViewModelAsync() => viewModelTask.JoinAsync(); @@ -123,7 +125,7 @@ public override IVsSearchTask CreateSearch(uint dwCookie, IVsSearchQuery pSearch if (pane != null) { - return new SearchTask(pane, dwCookie, pSearchQuery, pSearchCallback); + return new SearchTask(JoinableTaskFactory, pane, dwCookie, pSearchQuery, pSearchCallback); } return null; @@ -189,23 +191,29 @@ void UpdateSearchHost(bool enabled, string query) class SearchTask : VsSearchTask { + readonly JoinableTaskFactory joinableTaskFactory; readonly IGitHubPaneViewModel viewModel; public SearchTask( + JoinableTaskFactory joinableTaskFactory, IGitHubPaneViewModel viewModel, uint dwCookie, IVsSearchQuery pSearchQuery, IVsSearchCallback pSearchCallback) : base(dwCookie, pSearchQuery, pSearchCallback) { + this.joinableTaskFactory = joinableTaskFactory; this.viewModel = viewModel; } protected override void OnStartSearch() { - ThreadHelper.ThrowIfNotOnUIThread(); + joinableTaskFactory.RunAsync(async () => + { + await joinableTaskFactory.SwitchToMainThreadAsync(); + viewModel.SearchQuery = SearchQuery.SearchString; + }); - viewModel.SearchQuery = SearchQuery.SearchString; base.OnStartSearch(); } @@ -224,5 +232,7 @@ public SearchQuery(string query) public uint GetTokens(uint dwMaxTokens, IVsSearchToken[] rgpSearchTokens) => 0; } + + public JoinableTaskFactory JoinableTaskFactory { get; private set; } } } From 458b0d0631ff9bda5654b580cb7c18bf3e5f3b13 Mon Sep 17 00:00:00 2001 From: Jamie Cansdale Date: Fri, 11 Jan 2019 13:10:10 +0000 Subject: [PATCH 2/2] Remove workaround for UpdateSearchHost crash Now that OnStartSearch is updating IGitHubPaneViewModel on the UI thread, calling SearchAsync with a duplicate query no longer crashes. We no longer need to trim whitespace and compare. --- src/GitHub.VisualStudio/UI/GitHubPane.cs | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/GitHub.VisualStudio/UI/GitHubPane.cs b/src/GitHub.VisualStudio/UI/GitHubPane.cs index 2ab888224a..d0f04d4f42 100644 --- a/src/GitHub.VisualStudio/UI/GitHubPane.cs +++ b/src/GitHub.VisualStudio/UI/GitHubPane.cs @@ -177,13 +177,8 @@ void UpdateSearchHost(bool enabled, string query) { SearchHost.IsEnabled = enabled; - var searchString = SearchHost.SearchQuery?.SearchString; - if (searchString?.Trim() != query?.Trim()) + if (SearchHost.SearchQuery?.SearchString != query) { - // SearchAsync will crash the process if we send it a duplicate string. - // There is a SearchTrimsWhitespace setting that makes searched with leading or trailing - // white-space appear as duplicates. We compare the query with trimmed white-space to avoid this. - // https://github.com/github/VisualStudio/issues/1948 SearchHost.SearchAsync(query != null ? new SearchQuery(query) : null); } }