diff options
author | therzok <marius.ungureanu@xamarin.com> | 2019-12-02 16:37:15 +0300 |
---|---|---|
committer | monojenkins <jo.shields+jenkins@xamarin.com> | 2019-12-03 11:54:19 +0300 |
commit | b1006fae4280dcbd0a902932d36554e76e178adb (patch) | |
tree | 5d60df88e0518decb9a15d19e85d045ce09332be | |
parent | b505bbce1efd1d926c0b24c78fdd1b464815f84e (diff) |
Try a different fix
Synchronously run the OnInitialize of the service to load the addin assemblies on the UI thread, then dispatch the actual composing to a background task.
This should prevent deadlock issues, and ensure that the first init is called on the UI thread
-rw-r--r-- | main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Composition/CompositionManager.cs | 73 |
1 files changed, 33 insertions, 40 deletions
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Composition/CompositionManager.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Composition/CompositionManager.cs index 838daf1378..2cc3ca4b88 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Composition/CompositionManager.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Composition/CompositionManager.cs @@ -56,23 +56,12 @@ namespace MonoDevelop.Ide.Composition new AttributedPartDiscoveryV1 (StandardResolver), new AttributedPartDiscovery (StandardResolver, true)); - static Action HandleMefQueriedBeforeCompletion = UninitializedThrowException; - - static void UninitializedLogWarning () - => LoggingService.LogWarning ("UI thread queried MEF while it was still being built:{0}{1}", Environment.NewLine, Environment.StackTrace); - - static void UninitializedThrowException () - => throw new InvalidOperationException ("MEF queried while it was still being built"); - - static void ConfigureUninitializedMefHandling (bool throwException) - => HandleMefQueriedBeforeCompletion = throwException ? new Action (UninitializedThrowException) : new Action (UninitializedLogWarning); - public static CompositionManager Instance {
get {
if (instance == null) {
var task = Runtime.GetService<CompositionManager> ();
- if (!task.IsCompleted && Runtime.IsMainThread) {
- HandleMefQueriedBeforeCompletion ();
+ if (!task.IsCompleted) { + LoggingService.LogWarning ("UI thread queried MEF while it was still being built:{0}{1}", Environment.NewLine, Environment.StackTrace); }
instance = task.WaitAndGetResult ();
}
@@ -83,7 +72,19 @@ namespace MonoDevelop.Ide.Composition protected override Task OnInitialize (ServiceProvider serviceProvider) { - return Task.Run (async () => await InitializeInstanceAsync ());
+ Runtime.AssertMainThread (); + + var timings = new Dictionary<string, long> (); + var metadata = new CompositionLoadMetadata (timings); + + var timer = Counters.CompositionLoad.BeginTiming (metadata); + var stepTimer = System.Diagnostics.Stopwatch.StartNew (); + + var mefAssemblies = ReadAssembliesFromAddins (timer); + + timings ["ReadFromAddins"] = stepTimer.ElapsedMilliseconds; + + return Task.Run (() => InitializeInstanceAsync (timer, mefAssemblies)); } /// <summary> @@ -115,50 +116,42 @@ namespace MonoDevelop.Ide.Composition { } - async Task InitializeInstanceAsync () + async Task InitializeInstanceAsync (ITimeTracker<CompositionLoadMetadata> timer, HashSet<Assembly> mefAssemblies) {
- var timings = new Dictionary<string, long> ();
- var metadata = new CompositionLoadMetadata (timings);
-
- using (var timer = Counters.CompositionLoad.BeginTiming (metadata)) { - var fullTimer = System.Diagnostics.Stopwatch.StartNew ();
- var stepTimer = System.Diagnostics.Stopwatch.StartNew ();
-
- var mefAssemblies = await Runtime.RunInMainThread (() => ReadAssembliesFromAddins (timer)); - ConfigureUninitializedMefHandling (throwException: false); - timings ["ReadFromAddins"] = stepTimer.ElapsedMilliseconds;
- stepTimer.Restart ();
- - var caching = new Caching (mefAssemblies, new IdeRuntimeCompositionExceptionHandler ()); + var metadata = timer.Metadata; + var fullTimer = System.Diagnostics.Stopwatch.StartNew (); + var stepTimer = System.Diagnostics.Stopwatch.StartNew (); - // Try to use cached MEF data + var caching = new Caching (mefAssemblies, new IdeRuntimeCompositionExceptionHandler ()); + // Try to use cached MEF data + using (timer) { var canUse = metadata.ValidCache = caching.CanUse (); - if (canUse) {
+ if (canUse) { LoggingService.LogInfo ("Creating MEF composition from cache"); RuntimeComposition = await TryCreateRuntimeCompositionFromCache (caching); - }
- timings ["LoadFromCache"] = stepTimer.ElapsedMilliseconds;
+ } + metadata.Timings ["LoadFromCache"] = stepTimer.ElapsedMilliseconds; stepTimer.Restart (); // Otherwise fallback to runtime discovery. - if (RuntimeComposition == null) {
+ if (RuntimeComposition == null) { LoggingService.LogInfo ("Creating MEF composition from runtime"); - var (runtimeComposition, catalog) = await CreateRuntimeCompositionFromDiscovery (caching, timer);
+ var (runtimeComposition, catalog) = await CreateRuntimeCompositionFromDiscovery (caching, timer); RuntimeComposition = runtimeComposition; CachedComposition cacheManager = new CachedComposition (); caching.Write (RuntimeComposition, catalog, cacheManager).Ignore (); - }
- timings ["LoadRuntimeComposition"] = stepTimer.ElapsedMilliseconds;
- stepTimer.Restart ();
+ } + metadata.Timings ["LoadRuntimeComposition"] = stepTimer.ElapsedMilliseconds; + stepTimer.Restart (); ExportProviderFactory = RuntimeComposition.CreateExportProviderFactory (); ExportProvider = ExportProviderFactory.CreateExportProvider (); HostServices = Microsoft.VisualStudio.LanguageServices.VisualStudioMefHostServices.Create (ExportProvider); -
- timings ["CreateServices"] = stepTimer.ElapsedMilliseconds;
- metadata.Duration = fullTimer.ElapsedMilliseconds;
+ + metadata.Timings ["CreateServices"] = stepTimer.ElapsedMilliseconds; + metadata.Duration = fullTimer.ElapsedMilliseconds; }
}
|