Version Used: 1.3.2 (also repros in 2.0.0-rc2)
Steps to Reproduce:
Full repro code available at https://github.com/dpaoliello/PromiseNotToEnqueueRepro
This requires two threads:
Thread 1 (Main C# Compiler thread):
CommonCompiler.RunCore.CSharpCompilation.GetDeclarationDiagnostics.ForceComplete聽on symbols recursively.SymbolCompletionState.NotePartCompleted before calling CSharpCompilation.SymbolDeclaredEvent (e.g. SourceMemberFieldSymbol.FixedSize).NotePartCompleted the thread is suspended (note that SymbolDeclaredEvent has not yet been called).Thread 2 (Thread for analyzer):
CSharpCompilation.GetDiagnostics.ForceComplete聽on symbols recursively.GetDiagnostics then calls Compilation.EnsureCompilationEventQueueCompleted which marks the EventQueue聽as completed and promises not to enqueue any other events.Thread 1 then continues, and calls SymbolDeclaredEvent which attempts to enqueue the event, but聽finds that the queue has been completed, thus throws the InvalidOperationException.
There are two possible ways I can think of to fix this:
NotePartCompleted to ensure that all events are queued before completing the part.ForceComplete chain at a time - perhaps the first聽thread that does this can atomically set a task that other threads can then wait on.@dpaoliello You are awesome.
Resolved (fixed) in #16740 .
Most helpful comment
@dpaoliello You are awesome.