Blazor 应用程序中的异步调用永远挂起并且永远不会出错

Ioa*_*ana 4 c# client asynchronous blazor

我试图在 cs 类中调用异步方法,但页面冻结了。调试时,一切似乎都运行良好,直到上await thing.wait.WaitAsync();线。在该行之后,没有其他断点被击中(我周围有一堆断点,包括下一行上的一个),页面看起来像在继续加载,并且没有弹出错误/异常消息。

ApiClient_Test.razor

@if (myResult == null)
{
    <p><em>Loading...</em></p>
}
else
{
    <p>@myResult</p>
}
@code{
    private string myResult;

    protected override async Task OnInitializedAsync()
    {
    var test = new ApiClient_BlazorTest.ApiClientBlazorTests.ApiClient_TestAsync();
    myResult = test.MyMethod();
    }
}
Run Code Online (Sandbox Code Playgroud)

ApiClientTest.cs

namespace ApiClient_BlazorTest.ApiClientBlazorTests
{
    public class ApiClient_TestAsync : Controller
    {
        public string MyMethod()
        {
            var a = MyAsyncMethod();
            a.Wait();

            return a.Result;
        }

        public async Task<string> MyAsyncMethod()
        {
            var thing = new athing();

            // start a thing that takes 6 seconds
            thing.dothings();
            // await the thing
            await thing.wait.WaitAsync();
            return "ok";
        }

        private class athing
        {
            public SemaphoreSlim wait { get; set; } = new SemaphoreSlim(1);
            public string dothings()
            {
                wait.Wait();
                Task.Run(() => { Thread.Sleep(6000); wait.Release(); });
                return "";
            }
        }   
    }
}
Run Code Online (Sandbox Code Playgroud)

我在控制台应用程序上运行了相同的代码。那里一切都工作得很好。

有人在 blazor 和异步函数中见过类似的东西吗?

Ste*_*ary 8

Blazor 渲染有一个SynchronizationContext,因此阻塞异步代码可能会导致死锁

最好的解决方案是删除所有阻塞调用 - 即使用orawait代替:Wait()Result

public async Task<string> MyMethodAsync() // was `public string MyMethod()`
{
  var a = MyAsyncMethod();
  // await a; // was `a.Wait();`

  return await a; // was `return a.Result;`
}
Run Code Online (Sandbox Code Playgroud)

我在控制台应用程序上运行了相同的代码。那里一切都工作得很好。

控制台应用程序没有SynchronizationContext,因此在该环境中不会发生这种死锁。