-
Notifications
You must be signed in to change notification settings - Fork 4.2k
Move package initialization off the UI thread entirely #81756
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Move package initialization off the UI thread entirely #81756
Conversation
This removes the eager creation on the UI thread. To maintain compatibility with F# that accesses this on the UI thread, we'll fetch it on-demand in that case.
We had some code scheduling to the UI thread to wait for the UI context to be complete, but that's no longer necessary. Since we also had multiple derived types all setting this up, but all of them had the pattern in one way or another, this also just unifies the pattern to just one case.
This trick means we don't have to switch to the UI thread to call LoadPackage, but can stay on the background thread the whole time.
| get | ||
| { | ||
| Assumes.Present(_componentModel_doNotAccessDirectly); | ||
| return _componentModel_doNotAccessDirectly; | ||
| if (field is null) | ||
| { | ||
| // We should have been initialized asynchronously, but somebody is asking earlier than we expected, so fetch it synchronously. | ||
| var componentModel = (IComponentModel?)GetService(typeof(SComponentModel)); | ||
| Assumes.Present(componentModel); | ||
| field = componentModel; | ||
| return field; | ||
| } | ||
|
|
||
| return field; | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can this just be:
get => field ??= (IComponentModel?)GetService(typeof(SComponentModel)) ?? throw etc;
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we weren't using Assumes.Present, yes....hmmm....
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's why I have the throw :-)
| base.RegisterInitializeAsyncWork(packageInitializationTasks); | ||
|
|
||
| packageInitializationTasks.AddTask(isMainThreadTask: true, task: PackageInitializationMainThreadAsync); | ||
| packageInitializationTasks.AddTask(isMainThreadTask: false, task: PackageInitializationBackgroundThreadAsync); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nice.
This PR cleans up the final offenders so our package initialization for the C# package and the shared RoslynPackage do not transition to the UI thread anywhere. There are still UI thread transitions in the OnAfterPackageLoad, where we register event handlers for commands and object browser interfaces. VB is also still marked as not supporting background load to a COM marshalling issue to work around some legacy code.
At this point this somewhat moots the PackageLoadTasks infrastructure, but a follow-up will be made to this PR to remove that since that'll require some coordination and testing further.