Migrate to Microsoft.VisualStudio.Threading#28781
Conversation
…ispatcherPriority)
| _cancellationTokenSource.Token); | ||
|
|
||
| searcher.Search(); | ||
| _ = searcher.SearchAsync(); |
There was a problem hiding this comment.
Doesn't this have an effect of silencing all exceptions?
There was a problem hiding this comment.
➡️ It's an intermediate step. VSTHRD110 deals with observing the result of asynchronous operations.
There was a problem hiding this comment.
@sharwell intermediate step still needs fixing further?
There was a problem hiding this comment.
@jasonmalinowski Covered under the VSTHRD110 follow-up issue.
4e99053 to
fb1e11b
Compare
fb1e11b to
dc48c9b
Compare
2a93c17 to
059cd2f
Compare
b0cdbbc to
71c6f80
Compare
This comment was marked as resolved.
This comment was marked as resolved.
Sorry, something went wrong.
This comment was marked as resolved.
This comment was marked as resolved.
Sorry, something went wrong.
This comment was marked as resolved.
This comment was marked as resolved.
Sorry, something went wrong.
This comment was marked as resolved.
This comment was marked as resolved.
Sorry, something went wrong.
This comment was marked as resolved.
This comment was marked as resolved.
Sorry, something went wrong.
This comment was marked as resolved.
This comment was marked as resolved.
Sorry, something went wrong.
This comment was marked as resolved.
This comment was marked as resolved.
Sorry, something went wrong.
This comment was marked as resolved.
This comment was marked as resolved.
Sorry, something went wrong.
This comment was marked as resolved.
This comment was marked as resolved.
Sorry, something went wrong.
This comment was marked as resolved.
This comment was marked as resolved.
Sorry, something went wrong.
6401c77 to
c302b71
Compare
c302b71 to
23c08dd
Compare
| }, | ||
| ForegroundTaskScheduler); | ||
| CancellationToken.None, | ||
| TaskContinuationOptions.ExecuteSynchronously, |
There was a problem hiding this comment.
different options than usual. intentional?
There was a problem hiding this comment.
➡️ Situation is most similar to #28781 (comment), but has a dedicated follow-up item due to #28781 (comment)
|
My brain really hurts. |
And this is the easy change. 😄 |
|
@heejaechang @jaredpar @jasonmalinowski @CyrusNajmabadi @DustinCampbell I replied to the easy items, and will work on making requested changes and finishing my replies tomorrow. Thank you for the detailed reviews. 🏅 |
* Remove unused test constructors in QuickInfoCommandHandlerAndSourceProvider * Document `IThreadingContext`, `ThreadingContext`, and `DenyExecutionSynchronizationContext` * Ensure `DenyExecutionSynchronizationContext.ThrowIfSwitchOccurred` gets called during test cleanup * Clean up project layering by moving `StubVsEditorAdaptersFactoryService`
9d8b071 to
bb01d0e
Compare
jaredpar
left a comment
There was a problem hiding this comment.
The change looks good. I'd probably wait for one more IDE sign off though as I'm a bit out of my depth in a few places.
My biggest complaint is the lack of ConfigureAwait in places. I get that we cant add it because it's custom awaitable structs. But I feel like the readibility goes down a bit. Perhaps once we get a bit more used to the MS.VS.Threading this will go away.
DustinCampbell
left a comment
There was a problem hiding this comment.
Looks pretty good. I'll be interested in the follow ups that come later.
Note that this will almost certainly break insertions due to components that have IVT.
| AsynchronousOperationListenerProvider.NullListener, | ||
| null, | ||
| new SyntacticClassificationTaggerProvider(null, null, null)); | ||
| new SyntacticClassificationTaggerProvider(workspace.ExportProvider.GetExportedValue<IThreadingContext>(), null, null, null)); |
There was a problem hiding this comment.
nit: would be nice to name the null arguments.
| var view = new Mock<ITextView>(); | ||
| var producer = new BraceHighlightingViewTaggerProvider( | ||
| workspace.ExportProvider.GetExportedValue<IThreadingContext>(), | ||
| workspace.GetService<IBraceMatchingService>(), |
There was a problem hiding this comment.
TestWorkspace.GetService<TServiceInterface> is just a shortcut to call ExportProvider.GetExportedValue. Should we call one or the other consistently?
There was a problem hiding this comment.
➡️ 😦 I certainly should have used workspace.GetService<IThreadingContext>() here for consistency. I'll file a follow-up item related to the confusing pattern(s) we see today with these methods.
| _cancellationTokenSource.Token, | ||
| TaskContinuationOptions.OnlyOnRanToCompletion, | ||
| ForegroundTaskScheduler).CompletesAsyncOperation(asyncToken); | ||
| TaskContinuationOptions.OnlyOnRanToCompletion | TaskContinuationOptions.ExecuteSynchronously, |
There was a problem hiding this comment.
It'd be good if this were documented somewhere other than a comment buried in this PR (which has already "unicorned" on me twice! 😄). Since two very smart people have already asked about this pattern here, it'll almost certainly be stumbling block to anyone who happens upon the code. Maybe just add a comment in the code where the pattern is used? E.g. "ExecuteSynchronously is passed to avoid a situation where the continuation to be scheduled on a background thread before immediately switching to the main thread."
| _cancellationTokenSource.Token, | ||
| TaskContinuationOptions.OnlyOnRanToCompletion, | ||
| ForegroundTaskScheduler).CompletesAsyncOperation(asyncToken); | ||
| TaskContinuationOptions.OnlyOnRanToCompletion | TaskContinuationOptions.ExecuteSynchronously, |
There was a problem hiding this comment.
Or, maybe add a helper method with a good name to handle this situation rather than passing the same flags everytime? The exact same pattern is used below.
|
|
||
| [ImportingConstructor] | ||
| public QuickInfoPresenter(IQuickInfoBroker quickInfoBroker, DeferredContentFrameworkElementFactory elementFactory) | ||
| public QuickInfoPresenter(IThreadingContext threadingContext, IQuickInfoBroker quickInfoBroker, DeferredContentFrameworkElementFactory elementFactory) |
There was a problem hiding this comment.
Sounds good. Is there an issue tracking future work to update old code?
| public string DisplayName => FeaturesResources.Snippets; | ||
|
|
||
| public AbstractSnippetCommandHandler(IVsEditorAdaptersFactoryService editorAdaptersFactoryService, SVsServiceProvider serviceProvider) | ||
| public AbstractSnippetCommandHandler(IThreadingContext threadingContext, IVsEditorAdaptersFactoryService editorAdaptersFactoryService, SVsServiceProvider serviceProvider) |
There was a problem hiding this comment.
minor: Shouldn't this constructor be protected?
| internal IVsExpansionSession ExpansionSession; | ||
|
|
||
| public AbstractSnippetExpansionClient(Guid languageServiceGuid, ITextView textView, ITextBuffer subjectBuffer, IVsEditorAdaptersFactoryService editorAdaptersFactoryService) | ||
| public AbstractSnippetExpansionClient(IThreadingContext threadingContext, Guid languageServiceGuid, ITextView textView, ITextBuffer subjectBuffer, IVsEditorAdaptersFactoryService editorAdaptersFactoryService) |
There was a problem hiding this comment.
minor: protected constructor?
There was a problem hiding this comment.
| @@ -43,9 +43,11 @@ internal abstract class AbstractSnippetInfoService : ForegroundThreadAffinitized | |||
| private readonly IAsynchronousOperationListener _waiter; | |||
|
|
|||
| public AbstractSnippetInfoService( | |||
There was a problem hiding this comment.
minor: should this constructor on an abstract class be protected?
There was a problem hiding this comment.
➡️ Also covered by analyzer limitation
| Public Sub New(startActiveSession As Boolean) | ||
| MyBase.New(Nothing, Nothing, Nothing, Nothing) | ||
| Public Sub New(threadingContext As IThreadingContext, startActiveSession As Boolean) | ||
| MyBase.New(threadingContext, Nothing, Nothing, Nothing, Nothing) |
There was a problem hiding this comment.
minor: Named arguments for the trailing Nothing literals would be nice here.
There was a problem hiding this comment.
➡️ I would fix this if I was making other changes, but for now I'll consider it covered by #19186
| [ConditionalFact(typeof(VisualStudioMSBuildInstalled))] | ||
| [Trait(Traits.Feature, Traits.Features.MSBuildWorkspace)] | ||
| public async void TestAddRemoveMetadataReference_ReferenceAssembly() | ||
| public async Task TestAddRemoveMetadataReference_ReferenceAssembly() |
There was a problem hiding this comment.
good catch! I missed that one.
|
@dotnet/roslyn-infrastructure windows_debug_vs-integration_prtest is failing, but not due to this pull request. Merging and will file follow-up issues first thing tomorrow and start a deeper investigation into the failures. |
This change implements the first step towards Roslyn working in applications using vs-threading with reduced risk of concurrency bugs. Recommend reviewing by commit after looking at the full list to get an idea for the overall direction.
Most of the work in this change involves internal propagation of the
IThreadingContextinstance, which provides access to theJoinableTaskFactoryused in Roslyn code.Following this pull request, several diagnostics remain disabled.
FileAndForget" before enabling this diagnostic.Known follow-up issues (GitHub issues will be linked here once they are available):
WaitAndGetResultandWaitAndGetResult_CanCallOnBackgroundas problematic synchronous waits (blocked on Allow extensions for VSTHRD002 (Avoid problematic synchronous waits) microsoft/vs-threading#344)ForegroundThreadDataKind, and gut or eliminateForegroundThreadAffinitizedObjectMigrate to Microsoft.VisualStudio.Threading #28781 (comment)JoinableTaskContexta required import forThreadingContextMigrate to Microsoft.VisualStudio.Threading #28781 (comment)JoinableTaskFactoryTaskScheduler, or at least add it to the set of legacy thread switching types Migrate to Microsoft.VisualStudio.Threading #28781 (comment)AbstractPackage.ForegroundObject, and its costly initialization Migrate to Microsoft.VisualStudio.Threading #28781 (comment)ContinueWith,SafeContinueWith,StartNew,SafeStartNew, andTask.Runto identify cases where simpler approaches are viable Migrate to Microsoft.VisualStudio.Threading #28781 (comment)TestWorkspace.GetService<T>andTestWorkspace.ExportProvider.GetExportedValue<T>Migrate to Microsoft.VisualStudio.Threading #28781 (comment)Customer scenario
This is an internal code change that allows dotnet/roslyn to be more easily incorporated into applications that involve user interfaces and leverage the Microsoft.VisualStudio.Threading library for deadlock and reentrancy mitigation and overall best practices.
Bugs this fixes
N/A
Workarounds, if any
Fixing bugs as they occur.
Risk
This change has moderate risk, but I believe it's relatively low risk considering its scope since existing behaviors were preserved where possible. The primary points where I see risk are the following:
WaitAndGetResultwas weakened, the debug assertion it contained was strengthened substantially. This code does not affect release builds, but despite the work in this pull request it may continue to affect debug pull request builds.Performance impact
Performance should not change substantially as a direct result of this pull request. Over time, performance should improve by allowing more code to use asynchronous operations and more efficient task continuations.
Is this a regression from a previous update?
N/A
Root cause analysis
N/A
How was the bug found?
N/A
Test documentation updated?
N/A