Skip to content

[Vsintegration] Fix slow solution close in the code model - #2124

Merged
RobertvanderHulst merged 1 commit into
X-Sharp:devfrom
hpetriffer:fix/solution-close-reference-cleanup
Oct 26, 2026
Merged

RobertvanderHulst merged 1 commit into
X-Sharp:devfrom
hpetriffer:fix/solution-close-reference-cleanup

Conversation

@hpetriffer

Copy link
Copy Markdown
Contributor

Summary

Closing a large solution blocked the UI thread for minutes. Classic projects stayed at "0 of x projects" in the close dialog; SDK projects hung after "Closed solution".

XSolution.Close() closed each project, and every close removed that project from the references of all other projects. Each removed reference saved the reference list through the AssemblyReferences property, which runs ResolveReferences() and re-reads assemblies from disk. The database was already closed at that point, so all of this work was thrown away.

 XSolution.Close()
   XDatabase.CloseDatabase()
+  _projects.Clear()                       // list emptied first
   foreach project
-    project.UnLoad()
     project.Close()
       XSolution.Remove(project)
-        foreach otherProject
-          otherProject.RemoveProjectReference()
-            RemoveAssemblyReference()
-              SaveAssemblyReferencesToDatabase()
-                AssemblyReferences  -> ResolveReferences() -> XAssembly.Read()
+        returns at once (_projects is empty)
       UnLoad()

SaveAssemblyReferencesToDatabase() now passes the _AssemblyReferences field, so saving never triggers reference resolution.

Unloading or removing a single project still goes through XSolution.Remove() with the full reference cleanup.

Evidence

Intellisense log, time the code model needs on solution close:

  • Before (installed builds): RadixWfSDK.slnx (SDK, 110 projects, X# 3.1.0.0 in VS 18, closed ~2 minutes after opening): XSolution.Close() ran for more than 3 minutes after "Closed solution", with 26,000+ "Database is not open" calls on the UI thread. RadixWf.sln (98 classic projects, X# 3.0.x): 1–10 s normally, 13 and 17 minutes in two sessions.
    After (this branch, VS 2022 experimental instance, both solutions closed 1–2 minutes after loading): RadixWfSDK.slnx 3.8 s, RadixWf.sln 2.1 s. In both, nearly all of that time is SaveToDisk + VACUUM of the database; no XSolution.Remove() calls and no database access after the database was closed.

Merge Danger

Door: two-way

Blast Radius: solution-close

Only the code path for closing the whole solution changes. Not addressed here: CPS background threads still resolve references while the database is being closed, which logs InvalidOperationException and NullReferenceException in AssemblyReader.AddType. That race existed before this change and does not block the UI thread.

🤖 Generated with Claude Code

XSolution.Close() closed every project through XProject.Close(), which
called XSolution.Remove(). That removed the project from the references
of every other project in the solution, and each removed assembly
reference called SaveAssemblyReferencesToDatabase(). That method read the
AssemblyReferences property, which calls ResolveReferences() and can
re-read referenced assemblies from disk, while the database was already
closed. In large solutions this blocked the UI thread for minutes:
classic projects stayed at "0 of x projects" in the close dialog, SDK
projects hung after the solution was closed.

- XSolution.Close() now empties the project list before closing the
  projects, so XSolution.Remove() returns at once. Unloading or removing
  a single project still cleans up the references as before.
- SaveAssemblyReferencesToDatabase() passes the _AssemblyReferences field
  and no longer triggers ResolveReferences().

Measured in the VS 2022 experimental instance: RadixWf.sln (98 projects)
spends 2.1 s in the code model on close, RadixWfSDK.slnx 3.8 s, nearly all
of it saving the database. Before, closing took between seconds and
more than 3 minutes (RadixWfSDK.slnx), and up to 17 minutes (RadixWf.sln).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@RobertvanderHulst
RobertvanderHulst merged commit 664b9e7 into X-Sharp:dev Oct 26, 2026
1 check passed
@RobertvanderHulst

Copy link
Copy Markdown
Member

Great catch. This really makes a difference!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants