dotnet / aspnetcore

ASP.NET Core is a cross-platform .NET framework for building modern cloud-based web applications on Windows, Mac, or Linux.
https://asp.net
MIT License
35.38k stars 10k forks source link

[Blazor wasm] The CSharpCompilation.GetDiagnostics(CancellationToken) method throw System.PlatformNotSupportedException, when is called in the method, invoked as the first handler method by the user on the page #35113

Closed ekral closed 3 years ago

ekral commented 3 years ago

Describe the bug

Blazor wasm application:

When a user invokes the event handler method as the first method in the application, and this method calls CSharpCompilation.GetDiagnostics(CancellationToken) method, GetDiagnostics method throws System.PlatformNotSupportedException: Cannot wait on monitors on this runtime.

When a user invokes the event handler method as the second method in the application, and this method calls CSharpCompilation.GetDiagnostics(CancellationToken) method, there is no exception.

To Reproduce

Use case 1:

  1. Invoke RunCompliation method using "Run Compilation button"

result: System.PlatformNotSupportedException: Cannot wait on monitors on this runtime.

Use case 2:

  1. Invoke RunSync method using "Run sync" button.
  2. Invoke RunCompliation method using "Run Compilation button"

result: works as expected, writes "(1,5): warning CS0219: The variable 'x' is assigned but its value is never used" on console

Repository

@page "/"
@using Microsoft.CodeAnalysis
@using Microsoft.CodeAnalysis.CSharp

<button @onclick="RunSync">Run sync</button>
<button @onclick="RunCompilation">Run compilation</button>

@code
{
    [Inject]
    public HttpClient Client { get; set; }

    public async Task RunCompilation()
    {
        var stream = await Client.GetStreamAsync("_framework/System.Private.CoreLib.dll");
        MetadataReference reference = MetadataReference.CreateFromStream(stream);

        CSharpCompilation compilation = CSharpCompilation.Create("Test")
            .WithOptions(new CSharpCompilationOptions(OutputKind.ConsoleApplication))
            .AddReferences(new MetadataReference[] { reference })
            .AddSyntaxTrees(CSharpSyntaxTree.ParseText("int x = 0;", new CSharpParseOptions(LanguageVersion.Latest)));

        // Should write:
        // (1,5): warning CS0219: The variable 'x' is assigned but its value is never used
        foreach (Diagnostic diagnostic in compilation.GetDiagnostics())
        {
            Console.WriteLine(diagnostic.ToString());
        }
    }

    public void RunSync()
    {
        Console.WriteLine("void RunSync");
    }
}
<Project Sdk="Microsoft.NET.Sdk.BlazorWebAssembly">

  <PropertyGroup>
    <TargetFramework>net5.0</TargetFramework>
    <InvariantGlobalization>true</InvariantGlobalization>
    <BlazorEnableTimeZoneSupport>false</BlazorEnableTimeZoneSupport>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="5.0.8" />
    <PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="5.0.8" PrivateAssets="all" />
    <PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="3.10.0" />
    <PackageReference Include="System.Net.Http.Json" Version="5.0.0" />
  </ItemGroup>

</Project>

Exceptions

crit: Microsoft.AspNetCore.Components.WebAssembly.Rendering.WebAssemblyRenderer[100]
      Unhandled exception rendering component: Cannot wait on monitors on this runtime.
System.PlatformNotSupportedException: Cannot wait on monitors on this runtime.
   at System.Threading.Monitor.ObjWait(Boolean exitContext, Int32 millisecondsTimeout, Object obj)
   at System.Threading.Monitor.Wait(Object obj, Int32 millisecondsTimeout, Boolean exitContext)
   at System.Threading.Monitor.Wait(Object obj, Int32 millisecondsTimeout)
   at System.Threading.ManualResetEventSlim.Wait(Int32 millisecondsTimeout, CancellationToken cancellationToken)
   at System.Threading.Tasks.Task.SpinThenBlockingWait(Int32 millisecondsTimeout, CancellationToken cancellationToken)
   at System.Threading.Tasks.Task.InternalWaitCore(Int32 millisecondsTimeout, CancellationToken cancellationToken)
   at System.Threading.Tasks.Task.InternalWait(Int32 millisecondsTimeout, CancellationToken cancellationToken)
   at System.Threading.Tasks.Task.Wait(Int32 millisecondsTimeout, CancellationToken cancellationToken)
   at System.Threading.Tasks.Task.Wait()
   at System.Threading.Tasks.TaskReplicator.Replica.Wait()
   at System.Threading.Tasks.TaskReplicator.Run[RangeWorker](ReplicatableUserAction`1 action, ParallelOptions options, Boolean stopOnFirstFailure)
   at System.Threading.Tasks.Parallel.ForWorker[Object](Int32 fromInclusive, Int32 toExclusive, ParallelOptions parallelOptions, Action`1 body, Action`2 bodyWithState, Func`4 bodyWithLocal, Func`1 localInit, Action`1 localFinally)
   at System.Threading.Tasks.Parallel.For(Int32 fromInclusive, Int32 toExclusive, ParallelOptions parallelOptions, Action`1 body)
   at Roslyn.Utilities.RoslynParallel.For(Int32 fromInclusive, Int32 toExclusive, Action`1 body, CancellationToken cancellationToken)
   at Microsoft.CodeAnalysis.CSharp.CSharpCompilation.GetDiagnosticsWithoutFiltering(CompilationStage stage, Boolean includeEarlierStages, BindingDiagnosticBag builder, CancellationToken cancellationToken)
   at Microsoft.CodeAnalysis.CSharp.CSharpCompilation.GetDiagnostics(CompilationStage stage, Boolean includeEarlierStages, DiagnosticBag diagnostics, CancellationToken cancellationToken)
   at Microsoft.CodeAnalysis.CSharp.CSharpCompilation.GetDiagnostics(CompilationStage stage, Boolean includeEarlierStages, CancellationToken cancellationToken)
   at Microsoft.CodeAnalysis.CSharp.CSharpCompilation.GetDiagnostics(CancellationToken cancellationToken)
   at CSharpCompilationBlazorTest.Pages.Index.Run() in C:\Users\ekral\source\repos\CSharpCompilationBlazorTest\CSharpCompilationBlazorTest\Pages\Index.razor:line 22
   at Microsoft.AspNetCore.Components.ComponentBase.CallStateHasChangedOnAsyncCompletion(Task task)
   at Microsoft.AspNetCore.Components.RenderTree.Renderer.GetErrorHandledTask(Task taskToHandle)

Further technical details

Sada .NET SDK (s ohledem na libovolný soubor global.json):
 Version:   6.0.100-preview.6.21355.2
 Commit:    7f8e0d76c0

Běhové prostředí:
 OS Name:     Windows
 OS Version:  10.0.19043
 OS Platform: Windows
 RID:         win10-x64
 Base Path:   C:\Program Files\dotnet\sdk\6.0.100-preview.6.21355.2\

Host (useful for support):
  Version: 6.0.0-preview.6.21352.12
  Commit:  770d630b28

.NET SDKs installed:
  2.1.700 [C:\Program Files\dotnet\sdk]
  2.1.701 [C:\Program Files\dotnet\sdk]
  2.1.816 [C:\Program Files\dotnet\sdk]
  3.1.411 [C:\Program Files\dotnet\sdk]
  5.0.104 [C:\Program Files\dotnet\sdk]
  5.0.205 [C:\Program Files\dotnet\sdk]
  5.0.302 [C:\Program Files\dotnet\sdk]
  6.0.100-preview.6.21355.2 [C:\Program Files\dotnet\sdk]

.NET runtimes installed:
  Microsoft.AspNetCore.All 2.1.11 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
  Microsoft.AspNetCore.All 2.1.12 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
  Microsoft.AspNetCore.All 2.1.13 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
  Microsoft.AspNetCore.All 2.1.28 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
  Microsoft.AspNetCore.App 2.1.11 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 2.1.12 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 2.1.13 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 2.1.28 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 3.1.17 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 5.0.4 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 5.0.6 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 5.0.8 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 6.0.0-preview.6.21355.2 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.NETCore.App 2.1.11 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 2.1.12 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 2.1.13 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 2.1.28 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 3.1.17 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 5.0.4 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 5.0.6 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 5.0.8 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 6.0.0-preview.6.21352.12 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.WindowsDesktop.App 3.1.17 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
  Microsoft.WindowsDesktop.App 5.0.4 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
  Microsoft.WindowsDesktop.App 5.0.6 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
  Microsoft.WindowsDesktop.App 5.0.8 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
  Microsoft.WindowsDesktop.App 6.0.0-preview.6.21353.1 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
mkArtakMSFT commented 3 years ago

Hi. It looks like this is a question about how to use ASP.NET Core. While we do our best to look through all the issues filed here, we are not a general-purpose forum. To get a faster response we suggest posting your questions to StackOverflow using the blazor tag.

ekral commented 3 years ago

Thank you @mkArtakMSFT, I appretiate your time. I think it may be connected to this issue: https://github.com/dotnet/runtime/issues/43411 because Roslyn does use Parallel.For inside GetDiagnostics.

I still think it may be a bug. But as a temporal fix, I can set concurrentBuild option on CSharpCompilationOptions to false.