diff --git a/ICSharpCode.ILSpyX/AssemblyListManager.cs b/ICSharpCode.ILSpyX/AssemblyListManager.cs
index 35e1021ce..772062c9e 100644
--- a/ICSharpCode.ILSpyX/AssemblyListManager.cs
+++ b/ICSharpCode.ILSpyX/AssemblyListManager.cs
@@ -113,14 +113,16 @@ namespace ICSharpCode.ILSpyX
 		public void SaveList(AssemblyList list)
 		{
 			this.settingsProvider.Update(
-				delegate (XElement root) {
+				root => {
 					XElement? doc = root.Element("AssemblyLists");
 					if (doc == null)
 					{
 						doc = new XElement("AssemblyLists");
 						root.Add(doc);
 					}
-					XElement? listElement = doc.Elements("List").FirstOrDefault(e => (string?)e.Attribute("name") == list.ListName);
+
+					XElement? listElement = doc.Elements("List")
+						.FirstOrDefault(e => (string?)e.Attribute("name") == list.ListName);
 					if (listElement != null)
 						listElement.ReplaceWith(list.SaveAsXml());
 					else
@@ -163,13 +165,9 @@ namespace ICSharpCode.ILSpyX
 		{
 			AssemblyLists.Clear();
 			this.settingsProvider.Update(
-				delegate (XElement root) {
+				root => {
 					XElement? doc = root.Element("AssemblyLists");
-					if (doc == null)
-					{
-						return;
-					}
-					doc.Remove();
+					doc?.Remove();
 				});
 		}
 
diff --git a/ILSpy/App.xaml.cs b/ILSpy/App.xaml.cs
index d00eb4204..0665244f3 100644
--- a/ILSpy/App.xaml.cs
+++ b/ILSpy/App.xaml.cs
@@ -216,9 +216,6 @@ namespace ICSharpCode.ILSpy
 			}
 
 			MainWindow = new MainWindow();
-			MainWindow.Loaded += (sender, args) => {
-				ExportProvider.GetExportedValue<AssemblyTreeModel>().Initialize();
-			};
 			MainWindow.Show();
 		}
 
diff --git a/ILSpy/AssemblyTree/AssemblyTreeModel.cs b/ILSpy/AssemblyTree/AssemblyTreeModel.cs
index de8237b08..7986967a2 100644
--- a/ILSpy/AssemblyTree/AssemblyTreeModel.cs
+++ b/ILSpy/AssemblyTree/AssemblyTreeModel.cs
@@ -86,6 +86,8 @@ namespace ICSharpCode.ILSpy.AssemblyTree
 			SelectedItems.CollectionChanged += (_, _) => selectionChangeThrottle.Tick();
 
 			refreshThrottle = new DispatcherThrottle(DispatcherPriority.Background, RefreshInternal);
+
+			AssemblyList = SettingsService.Instance.CreateEmptyAssemblyList();
 		}
 
 		private void Settings_PropertyChanged(object? sender, PropertyChangedEventArgs e)
@@ -121,7 +123,7 @@ namespace ICSharpCode.ILSpy.AssemblyTree
 			}
 		}
 
-		public AssemblyList? AssemblyList { get; private set; }
+		public AssemblyList AssemblyList { get; private set; }
 
 		private SharpTreeNode? root;
 		public SharpTreeNode? Root {
@@ -205,7 +207,7 @@ namespace ICSharpCode.ILSpy.AssemblyTree
 						{
 							// FindNamespaceNode() blocks the UI if the assembly is not yet loaded,
 							// so use an async wait instead.
-							await asm.GetMetadataFileAsync().Catch<Exception>(ex => { });
+							await asm.GetMetadataFileAsync().Catch<Exception>(_ => { });
 							NamespaceTreeNode nsNode = asmNode.FindNamespaceNode(namespaceName);
 							if (nsNode != null)
 							{
@@ -260,7 +262,7 @@ namespace ICSharpCode.ILSpy.AssemblyTree
 			else if (spySettings != null)
 			{
 				SharpTreeNode? node = null;
-				if (activeTreeViewPath?.Length > 0 && AssemblyList != null)
+				if (activeTreeViewPath?.Length > 0)
 				{
 					foreach (var asm in AssemblyList.GetAssemblies())
 					{
@@ -268,7 +270,7 @@ namespace ICSharpCode.ILSpy.AssemblyTree
 						{
 							// FindNodeByPath() blocks the UI if the assembly is not yet loaded,
 							// so use an async wait instead.
-							await asm.GetMetadataFileAsync().Catch<Exception>(ex => { });
+							await asm.GetMetadataFileAsync().Catch<Exception>(_ => { });
 						}
 					}
 					node = FindNodeByPath(activeTreeViewPath, true);
@@ -401,7 +403,7 @@ namespace ICSharpCode.ILSpy.AssemblyTree
 		{
 			AssemblyList list = SettingsService.Instance.AssemblyListManager.LoadList(name);
 			//Only load a new list when it is a different one
-			if (list.ListName != AssemblyList?.ListName)
+			if (list.ListName != AssemblyList.ListName)
 			{
 				ShowAssemblyList(list);
 				SelectNode(Root);
@@ -411,12 +413,9 @@ namespace ICSharpCode.ILSpy.AssemblyTree
 		private void ShowAssemblyList(AssemblyList assemblyList)
 		{
 			history.Clear();
-			if (this.AssemblyList != null)
-			{
-				this.AssemblyList.CollectionChanged -= assemblyList_CollectionChanged;
-			}
 
-			this.AssemblyList = assemblyList;
+			AssemblyList.CollectionChanged -= assemblyList_CollectionChanged;
+			AssemblyList = assemblyList;
 
 			assemblyList.CollectionChanged += assemblyList_CollectionChanged;
 
@@ -527,11 +526,6 @@ namespace ICSharpCode.ILSpy.AssemblyTree
 				return;
 			}
 
-			if (SelectedItems.SequenceEqual(nodesList))
-			{
-				return;
-			}
-
 			if (this.isNavigatingHistory)
 			{
 				SelectedItems.Clear();
@@ -649,8 +643,6 @@ namespace ICSharpCode.ILSpy.AssemblyTree
 					MainWindow.OpenLink(opCode.Link);
 					break;
 				case EntityReference unresolvedEntity:
-					if (AssemblyList is null)
-						break;
 					string protocol = unresolvedEntity.Protocol;
 					var file = unresolvedEntity.ResolveAssembly(AssemblyList);
 					if (file == null)
@@ -696,8 +688,6 @@ namespace ICSharpCode.ILSpy.AssemblyTree
 				AssemblyTreeNode? lastNode = null;
 
 				var assemblyList = AssemblyList;
-				if (assemblyList is null)
-					return;
 
 				foreach (string file in fileNames)
 				{
@@ -907,11 +897,7 @@ namespace ICSharpCode.ILSpy.AssemblyTree
 			{
 				var path = GetPathForNode(SelectedItem);
 
-				if (AssemblyList != null)
-				{
-					ShowAssemblyList(SettingsService.Instance.AssemblyListManager.LoadList(AssemblyList.ListName));
-				}
-
+				ShowAssemblyList(SettingsService.Instance.AssemblyListManager.LoadList(AssemblyList.ListName));
 				SelectNode(FindNodeByPath(path, true), inNewTabPage: false);
 
 				RefreshDecompiledView();
@@ -940,7 +926,7 @@ namespace ICSharpCode.ILSpy.AssemblyTree
 		{
 			using (activeView?.LockUpdates())
 			{
-				AssemblyList?.Sort(AssemblyComparer.Instance);
+				AssemblyList.Sort(AssemblyComparer.Instance);
 			}
 		}
 
diff --git a/ILSpy/Commands/RemoveAssembliesWithLoadErrors.cs b/ILSpy/Commands/RemoveAssembliesWithLoadErrors.cs
index 9cc357374..b0bc068c8 100644
--- a/ILSpy/Commands/RemoveAssembliesWithLoadErrors.cs
+++ b/ILSpy/Commands/RemoveAssembliesWithLoadErrors.cs
@@ -19,6 +19,7 @@
 using System.ComponentModel.Composition;
 using System.Linq;
 
+using ICSharpCode.ILSpy.AssemblyTree;
 using ICSharpCode.ILSpy.Properties;
 
 namespace ICSharpCode.ILSpy
@@ -27,18 +28,26 @@ namespace ICSharpCode.ILSpy
 	[PartCreationPolicy(CreationPolicy.Shared)]
 	class RemoveAssembliesWithLoadErrors : SimpleCommand
 	{
+		private readonly AssemblyTreeModel assemblyTreeModel;
+
+		[ImportingConstructor]
+		public RemoveAssembliesWithLoadErrors(AssemblyTreeModel assemblyTreeModel)
+		{
+			this.assemblyTreeModel = assemblyTreeModel;
+		}
+
 		public override bool CanExecute(object parameter)
 		{
-			return MainWindow.Instance.AssemblyTreeModel.AssemblyList?.GetAssemblies().Any(l => l.HasLoadError) == true;
+			return assemblyTreeModel.AssemblyList.GetAssemblies().Any(l => l.HasLoadError);
 		}
 
 		public override void Execute(object parameter)
 		{
-			foreach (var asm in MainWindow.Instance.AssemblyTreeModel.AssemblyList.GetAssemblies())
+			foreach (var assembly in assemblyTreeModel.AssemblyList.GetAssemblies())
 			{
-				if (!asm.HasLoadError)
+				if (!assembly.HasLoadError)
 					continue;
-				var node = MainWindow.Instance.AssemblyTreeModel.FindAssemblyNode(asm);
+				var node = MainWindow.Instance.AssemblyTreeModel.FindAssemblyNode(assembly);
 				if (node != null && node.CanDelete())
 					node.Delete();
 			}
@@ -49,14 +58,22 @@ namespace ICSharpCode.ILSpy
 	[PartCreationPolicy(CreationPolicy.Shared)]
 	class ClearAssemblyList : SimpleCommand
 	{
+		private readonly AssemblyTreeModel assemblyTreeModel;
+
+		[ImportingConstructor]
+		public ClearAssemblyList(AssemblyTreeModel assemblyTreeModel)
+		{
+			this.assemblyTreeModel = assemblyTreeModel;
+		}
+
 		public override bool CanExecute(object parameter)
 		{
-			return MainWindow.Instance.AssemblyTreeModel.AssemblyList?.Count > 0;
+			return assemblyTreeModel.AssemblyList.Count > 0;
 		}
 
 		public override void Execute(object parameter)
 		{
-			MainWindow.Instance.AssemblyTreeModel.AssemblyList?.Clear();
+			assemblyTreeModel.AssemblyList.Clear();
 		}
 	}
 }
diff --git a/ILSpy/Docking/CloseAllDocumentsCommand.cs b/ILSpy/Docking/CloseAllDocumentsCommand.cs
index 2c0ceb41b..14169498f 100644
--- a/ILSpy/Docking/CloseAllDocumentsCommand.cs
+++ b/ILSpy/Docking/CloseAllDocumentsCommand.cs
@@ -1,9 +1,4 @@
-using System;
-using System.Collections.Generic;
-using System.ComponentModel.Composition;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
+using System.ComponentModel.Composition;
 
 using ICSharpCode.ILSpy.Properties;
 
diff --git a/ILSpy/Docking/DockWorkspace.cs b/ILSpy/Docking/DockWorkspace.cs
index 9ca68cc26..057cd0f14 100644
--- a/ILSpy/Docking/DockWorkspace.cs
+++ b/ILSpy/Docking/DockWorkspace.cs
@@ -17,6 +17,7 @@
 // DEALINGS IN THE SOFTWARE.
 
 using System;
+using System.Collections.Generic;
 using System.Collections.ObjectModel;
 using System.Collections.Specialized;
 using System.Linq;
@@ -51,13 +52,17 @@ namespace ICSharpCode.ILSpy.Docking
 		public static readonly DockWorkspace Instance = new();
 
 		private readonly ObservableCollection<TabPageModel> tabPages = [];
-		private readonly ObservableCollection<ToolPaneModel> toolPanes = [];
 
 		private DockWorkspace()
 		{
 			this.tabPages.CollectionChanged += TabPages_CollectionChanged;
 			TabPages = new(tabPages);
-			ToolPanes = new(toolPanes);
+
+			ToolPanes = exportProvider
+				.GetExportedValues<ToolPaneModel>("ToolPane")
+				.OrderBy(item => item.Title)
+				.ToArray()
+				.AsReadOnly();
 
 			// Make sure there is at least one tab open
 			AddTabPage();
@@ -83,11 +88,16 @@ namespace ICSharpCode.ILSpy.Docking
 					.ExceptNullItems()
 					.Any(assemblyNode => !e.OldItems.Contains(assemblyNode.LoadedAssembly));
 
-				if (!found && tabPages.Count > 1)
+				if (!found)
 				{
 					tabPages.Remove(tab);
 				}
 			}
+
+			if (tabPages.Count == 0)
+			{
+				AddTabPage();
+			}
 		}
 
 		private void TabPages_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
@@ -117,11 +127,11 @@ namespace ICSharpCode.ILSpy.Docking
 
 		public ReadOnlyObservableCollection<TabPageModel> TabPages { get; }
 
-		public ReadOnlyObservableCollection<ToolPaneModel> ToolPanes { get; }
+		public ReadOnlyCollection<ToolPaneModel> ToolPanes { get; }
 
 		public bool ShowToolPane(string contentId)
 		{
-			var pane = toolPanes.FirstOrDefault(p => p.ContentId == contentId);
+			var pane = ToolPanes.FirstOrDefault(p => p.ContentId == contentId);
 			if (pane != null)
 			{
 				pane.Show();
@@ -132,10 +142,15 @@ namespace ICSharpCode.ILSpy.Docking
 
 		public void Remove(PaneModel model)
 		{
-			if (model is TabPageModel document)
-				tabPages.Remove(document);
-			if (model is ToolPaneModel tool)
-				tool.IsVisible = false;
+			switch (model)
+			{
+				case TabPageModel document:
+					tabPages.Remove(document);
+					break;
+				case ToolPaneModel tool:
+					tool.IsVisible = false;
+					break;
+			}
 		}
 
 		private TabPageModel activeTabPage = null;
@@ -166,10 +181,6 @@ namespace ICSharpCode.ILSpy.Docking
 
 		public void InitializeLayout(DockingManager manager)
 		{
-			var panes = exportProvider.GetExportedValues<ToolPaneModel>("ToolPane").OrderBy(item => item.Title);
-
-			this.toolPanes.AddRange(panes);
-
 			manager.LayoutUpdateStrategy = this;
 			XmlLayoutSerializer serializer = new XmlLayoutSerializer(manager);
 			serializer.LayoutSerializationCallback += LayoutSerializationCallback;
@@ -188,13 +199,13 @@ namespace ICSharpCode.ILSpy.Docking
 			switch (e.Model)
 			{
 				case LayoutAnchorable la:
-					e.Content = this.toolPanes.FirstOrDefault(p => p.ContentId == la.ContentId);
+					e.Content = this.ToolPanes.FirstOrDefault(p => p.ContentId == la.ContentId);
 					e.Cancel = e.Content == null;
 					la.CanDockAsTabbedDocument = false;
-					if (!e.Cancel)
+					if (e.Content is ToolPaneModel toolPaneModel)
 					{
-						e.Cancel = ((ToolPaneModel)e.Content).IsVisible;
-						((ToolPaneModel)e.Content).IsVisible = true;
+						e.Cancel = toolPaneModel.IsVisible;
+						toolPaneModel.IsVisible = true;
 					}
 					break;
 				default:
@@ -220,16 +231,14 @@ namespace ICSharpCode.ILSpy.Docking
 
 		internal void CloseAllTabs()
 		{
-			foreach (var doc in tabPages.ToArray())
-			{
-				if (doc.IsCloseable)
-					tabPages.Remove(doc);
-			}
+			var activePage = ActiveTabPage;
+
+			tabPages.RemoveWhere(page => page != activePage);
 		}
 
 		internal void ResetLayout()
 		{
-			foreach (var pane in toolPanes)
+			foreach (var pane in ToolPanes)
 			{
 				pane.IsVisible = false;
 			}
diff --git a/ILSpy/MainWindow.xaml.cs b/ILSpy/MainWindow.xaml.cs
index c5232ef83..53fd1f30f 100644
--- a/ILSpy/MainWindow.xaml.cs
+++ b/ILSpy/MainWindow.xaml.cs
@@ -25,6 +25,7 @@ using System.Threading.Tasks;
 using System.Windows;
 using System.Windows.Input;
 using System.Windows.Media;
+using System.Windows.Threading;
 
 using AvalonDock.Layout.Serialization;
 
@@ -70,11 +71,14 @@ namespace ICSharpCode.ILSpy
 
 			InitializeComponent();
 
-			mainWindowViewModel.Workspace.InitializeLayout(dockManager);
+			InitFileLoaders();
 
-			MenuService.Instance.Init(mainMenu, toolBar, InputBindings);
+			Dispatcher.BeginInvoke(DispatcherPriority.Background, () => {
+				mainWindowViewModel.Workspace.InitializeLayout(dockManager);
+				MenuService.Instance.Init(mainMenu, toolBar, InputBindings);
 
-			InitFileLoaders();
+				Dispatcher.BeginInvoke(DispatcherPriority.Background, AssemblyTreeModel.Initialize);
+			});
 		}
 
 		void SetWindowBounds(Rect bounds)
diff --git a/ILSpy/Util/MenuService.cs b/ILSpy/Util/MenuService.cs
index d364ad438..a42e8c35a 100644
--- a/ILSpy/Util/MenuService.cs
+++ b/ILSpy/Util/MenuService.cs
@@ -142,7 +142,7 @@ namespace ICSharpCode.ILSpy.Util
 
 			windowMenuItem.Items.Clear();
 
-			var toolItems = dockWorkspace.ToolPanes.ObservableSelect(toolPane => CreateMenuItem(toolPane, inputBindings));
+			var toolItems = dockWorkspace.ToolPanes.Select(toolPane => CreateMenuItem(toolPane, inputBindings)).ToArray();
 			var tabItems = dockWorkspace.TabPages.ObservableSelect(tabPage => CreateMenuItem(tabPage, dockWorkspace));
 
 			var allItems = new ObservableCompositeCollection<Control>(defaultItems, [new Separator()], toolItems, [new Separator()], tabItems);
diff --git a/ILSpy/Util/SettingsService.cs b/ILSpy/Util/SettingsService.cs
index def1ccf21..bd2923e2e 100644
--- a/ILSpy/Util/SettingsService.cs
+++ b/ILSpy/Util/SettingsService.cs
@@ -152,6 +152,11 @@ namespace ICSharpCode.ILSpy.Util
 			}
 		}
 
+		public AssemblyList CreateEmptyAssemblyList()
+		{
+			return AssemblyListManager.CreateList(string.Empty);
+		}
+
 		private bool reloading;
 
 		public void Reload()