Move VisualStudioTaskSchedulerProvider to the EditorFeatures layer#48662
Move VisualStudioTaskSchedulerProvider to the EditorFeatures layer#48662sharwell merged 3 commits intodotnet:masterfrom
Conversation
|
@sharwell: it's unclear to me why this actually fixes it. Specifically, what's causing this relationship:
I have a guess, but I'd rather the PR was clear. 😄 More generally, the change in general makes me hesitate too: if I could remove the VisualStudioWorkspace task scheduler without breaking people I'd do so in an instant; us putting this on a UI thread is something we absolutely regret. Moving this to EditorFeatures seems to be doubling down on it, and also could potentially break other hosts that didn't want this. For example, what is the impact here for VS for Mac? |
The default task scheduler prior to this change is obtained here: For XUnit tests, the current context scheduler becomes There are three primary options for correcting this:
Other applications will either fall into a bucket where the default task scheduler provider worked as-is (and the new one will also work), or they were already using one of the above workarounds. |
|
Ah, so xUnit will wait for work scheduled to the AsyncTestSyncContext, but it does that after our UseExportProviderAttribute.After runs? Even though I'm not a fan of tests being async void, but wouldn't those be broken too, which is why I understand xUnit has the special sync context in the first place? |
I guess I could totally imagine a host where the Workspace gets created on a background thread, and this is changing behavior now. I guess of your options presented I'd do the first -- move the code down but still leave the exporting explicit for tests and the VS layer. But my earlier question still stands -- something seems more fundamentally off here first. |
|
Although I guess you could argue that if we break a host with this change, they were already on pretty thin ice if they were that sensitive for which thread they were on in the first place. I'm also not sure whether we care about cases where they are MEF importing editor features but don't export IThreadingContext as a host like CodeFlow. I guess your provider would MEF reject, but I'm not sure to what end precisely. |
IThreadingContext (and JTF) is required for the EditorFeatures layer, and any host using this layer already supports it. There is no main thread requirement though, and this provider handles both cases. Note that the service default layer for this service was changed to Editor, so any host providing their own implementation of this service would not be impacted (as it would be using Host). |
You're right, since at this point even the editor itself more or less requires it. Not sure what I was thinking there. So I agree this fix doesn't really break anything or change behavior, but my other question is unanswered: if work is being scheduled to AsyncTestSyncContext, why is xUnit not waiting for that prior to running the after test handler? Am I misunderstanding the xUnit design here? |
src/EditorFeatures/Core/Shared/Utilities/VisualStudioTaskSchedulerProvider.cs
Outdated
Show resolved
Hide resolved
| namespace Microsoft.CodeAnalysis.Editor.Shared.Utilities | ||
| { | ||
| [ExportWorkspaceService(typeof(ITaskSchedulerProvider), ServiceLayer.Host), Shared] | ||
| [ExportWorkspaceService(typeof(ITaskSchedulerProvider), ServiceLayer.Editor), Shared] |
There was a problem hiding this comment.
I admit I wish we had a comment here that this is the default being provided for back compat, but we encourage new hosts who can do so to override this behavior and run WorkspaceChanged off the main thread.
There was a problem hiding this comment.
If new hosts are out-of-process, they wouldn't have a main thread and this is automatic. 😄
There was a problem hiding this comment.
Well, out of proc hosts aren't importing this layer in the first place. I was thinking more for things like VS for Mac or something. But yeah, not sure how many other ones we might still have of that.
If the test method returns |
|
@sharwell: for defense in depth should we also be updating our code to wait on that as well, or fail the test if there's still pending work to catch other issues like this? I'm also a bit confused then looking at it because it seems AsyncTestSyncContext itself just either runs things to the thread pool or simply pushes them to the underlying context. So:
Makes me wonder what the underlying context was and why it was interfering as well. |
|
@jasonmalinowski The root cause of the test failures was a processing delay for things queued to the main thread with lower priority than a yield operation also running on the main thread. The yield is being fixed by #44514. |
Prior to this change, tests in the EditorFeatures layer were using JTF through
IThreadingContext, but didn't pull in a JTF-aware task scheduler provider because it was up in the Visual Studio layer. Moving the JTF-aware scheduler down to the EditorFeatures layer causes UseExportProviderAttribute.After to dispatch through JTF instead of trying to dispatch through XUnit's test synchronization context, which doesn't end up running on the WPF dispatcher.Fixes #48644