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

Commit 68d098a

Browse files
committed
Do initialization asynchronously on Main thread
This will allow this service to be used by a package that is initializing on a background thread.
1 parent 5200e72 commit 68d098a

File tree

2 files changed

+48
-27
lines changed

2 files changed

+48
-27
lines changed

src/GitHub.TeamFoundation.14/Services/VSGitExt.cs

Lines changed: 45 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
using GitHub.Models;
77
using GitHub.Services;
88
using GitHub.Logging;
9+
using GitHub.Helpers;
910
using GitHub.TeamFoundation.Services;
1011
using Serilog;
1112
using Microsoft.VisualStudio.TeamFoundation.Git.Extensibility;
@@ -46,45 +47,72 @@ public VSGitExt(IGitHubServiceProvider serviceProvider, IVSUIContextFactory fact
4647
// Start with empty array until we have a chance to initialize.
4748
ActiveRepositories = Array.Empty<ILocalRepositoryModel>();
4849

49-
if (context.IsActive && TryInitialize())
50+
PendingTasks = InitializeAsync();
51+
}
52+
53+
async Task InitializeAsync()
54+
{
55+
try
5056
{
51-
// Refresh ActiveRepositories on background thread so we don't delay startup.
52-
QueueRefreshActiveRepositories();
57+
if (!context.IsActive || !await TryInitialize())
58+
{
59+
// If we're not in the UIContext or TryInitialize fails, have another go when the UIContext changes.
60+
context.UIContextChanged += ContextChanged;
61+
log.Debug("VSGitExt will be initialized later");
62+
}
5363
}
54-
else
64+
catch (Exception e)
5565
{
56-
// If we're not in the UIContext or TryInitialize fails, have another go when the UIContext changes.
57-
context.UIContextChanged += ContextChanged;
58-
log.Debug("VSGitExt will be initialized later");
66+
log.Error(e, "Initializing");
5967
}
6068
}
6169

6270
void ContextChanged(object sender, VSUIContextChangedEventArgs e)
6371
{
64-
// If we're in the UIContext and TryInitialize succeeds, we can stop listening for events.
65-
// NOTE: this event can fire with UIContext=true in a TFS solution (not just Git).
66-
if (e.Activated && TryInitialize())
72+
if (e.Activated)
6773
{
68-
// Refresh ActiveRepositories on background thread so we don't delay UI context change.
69-
QueueRefreshActiveRepositories();
70-
context.UIContextChanged -= ContextChanged;
71-
log.Debug("Initialized VSGitExt on UIContextChanged");
74+
PendingTasks = ContextChangedAsync();
7275
}
7376
}
7477

75-
bool TryInitialize()
78+
async Task ContextChangedAsync()
7679
{
80+
try
81+
{
82+
// If we're in the UIContext and TryInitialize succeeds, we can stop listening for events.
83+
// NOTE: this event can fire with UIContext=true in a TFS solution (not just Git).
84+
if (await TryInitialize())
85+
{
86+
context.UIContextChanged -= ContextChanged;
87+
log.Debug("Initialized VSGitExt on UIContextChanged");
88+
}
89+
}
90+
catch (Exception e)
91+
{
92+
log.Error(e, "UIContextChanged");
93+
}
94+
}
95+
96+
async Task<bool> TryInitialize()
97+
{
98+
// GetService must be called on the Main thread.
99+
await ThreadingHelper.SwitchToMainThreadAsync();
100+
77101
gitService = serviceProvider.GetService<IGitExt>();
78102
if (gitService != null)
79103
{
80104
gitService.PropertyChanged += (s, e) =>
81105
{
82106
if (e.PropertyName == nameof(gitService.ActiveRepositories))
83107
{
84-
QueueRefreshActiveRepositories();
108+
// Execute tasks in sequence using thread pool (TaskScheduler.Default).
109+
PendingTasks = PendingTasks.ContinueWith(_ => RefreshActiveRepositories(), TaskScheduler.Default);
85110
}
86111
};
87112

113+
// Do this after we start listening so we don't miss an event.
114+
await Task.Run(() => RefreshActiveRepositories());
115+
88116
log.Debug("Found IGitExt service and initialized VSGitExt");
89117
return true;
90118
}
@@ -93,12 +121,6 @@ bool TryInitialize()
93121
return false;
94122
}
95123

96-
void QueueRefreshActiveRepositories()
97-
{
98-
// Execute tasks in sequence using thread pool (TaskScheduler.Default).
99-
PendingTasks = PendingTasks.ContinueWith(_ => RefreshActiveRepositories(), TaskScheduler.Default);
100-
}
101-
102124
void RefreshActiveRepositories()
103125
{
104126
try
@@ -140,6 +162,6 @@ private set
140162
/// <summary>
141163
/// Tasks that are pending execution on the thread pool.
142164
/// </summary>
143-
public Task PendingTasks { get; private set; } = Task.CompletedTask;
165+
public Task PendingTasks { get; private set; }
144166
}
145167
}

test/UnitTests/GitHub.TeamFoundation/VSGitExtTests.cs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,10 @@
1111
using Microsoft.VisualStudio.TeamFoundation.Git.Extensibility;
1212
using System.Threading.Tasks;
1313
using System.Linq;
14-
using GitHub.TeamFoundation.Services;
1514

1615
public class VSGitExtTests
1716
{
18-
public class TheConstructor
17+
public class TheConstructor : TestBaseClass
1918
{
2019
[TestCase(true, 1)]
2120
[TestCase(false, 0)]
@@ -60,7 +59,7 @@ public void ActiveRepositories_ReadUsingThreadPoolThread()
6059
}
6160
}
6261

63-
public class TheActiveRepositoriesChangedEvent
62+
public class TheActiveRepositoriesChangedEvent : TestBaseClass
6463
{
6564
[Test]
6665
public async Task GitExtPropertyChangedEvent_ActiveRepositoriesChangedIsFired()
@@ -132,7 +131,7 @@ public void WhenUIContextChanged_FiredUsingThreadPoolThread()
132131
}
133132
}
134133

135-
public class TheActiveRepositoriesProperty
134+
public class TheActiveRepositoriesProperty : TestBaseClass
136135
{
137136
[Test]
138137
public void SccProviderContextNotActive_IsEmpty()

0 commit comments

Comments
 (0)