Blazor-Wasm:为什么 `await Task` 会阻塞 UI,但 `await`-`async` 不会?
Blazor-Wasm: Why does `await Task` blocks UI, but `await`-`async` doesn't?
我目前正在尝试在 blazor WASM 中异步调用一个昂贵的方法,同时不阻塞 UI 线程。
根据 , it is impossible. However, these date back to a couple of years ago, and according to the WebAssembly roadmap 的回答,现代浏览器支持线程。
此外,我可以 await
函数调用而不阻塞 UI 线程,只要函数是自下而上等待的。
在下面的代码片段中,单击 Foo
按钮将导致 UI 在执行操作时挂起几秒钟,但单击 Bar
按钮将在后台处理类似(但可等待)的操作,同时保持 UI 响应。
如果 WebAssembly 不支持多线程,为什么第二个选项似乎适用于多线程?如果支持多线程,为什么第一个选项会阻塞UI?
@page "/asynctest"
<div class="row">
<div class="col">
@DisplayValue
</div>
<div class="col">
<button type="button" @onclick="OnClickFoo">Foo</button>
</div>
<div class="col">
<button type="button" @onclick="OnClickBar">Bar</button>
</div>
</div>
@code{
private string DisplayValue = "";
private double Result;
private async Task OnClickFoo(EventArgs e)
{
DisplayValue = "Working...";
Result = await Task.Run(() => Frobnicate()); // Blocks UI thread
DisplayValue = Result.ToString();
}
private async Task OnClickBar(EventArgs e)
{
DisplayValue = "Working...";
Result = await FrobnicateAsync(); // Doesn't block UI thread
DisplayValue = Result.ToString();
}
private int Frobnicate()
{
Thread.Sleep(2000); // do some heavy work
return 42;
}
private async Task<int> FrobnicateAsync()
{
await Task.Delay(2000); // do some heavy work async
return 42;
}
}
据我所知,Blazor WASM 不支持多线程,你只能得到 1 个线程。
在“OnClickBar”方法中,您没有创建不同的线程。您正在使用 async/await 状态机,它 returns 控制调用线程。 Task.Delay(2000)
不会阻塞线程,如 Stack Overflow question
所示
在“OnClickFoo”方法中,您正在调用 Task.Run,它会尝试创建一个后台线程 - 这在 WASM 中无法正常工作,因为您只有一个线程,所以当您调用 Thread.Sleep(2000);
- UI 线程正在休眠。
在此处了解有关线程的更多信息:Microsoft Docs - Threads
相关堆栈溢出
我目前正在尝试在 blazor WASM 中异步调用一个昂贵的方法,同时不阻塞 UI 线程。
根据
此外,我可以 await
函数调用而不阻塞 UI 线程,只要函数是自下而上等待的。
在下面的代码片段中,单击 Foo
按钮将导致 UI 在执行操作时挂起几秒钟,但单击 Bar
按钮将在后台处理类似(但可等待)的操作,同时保持 UI 响应。
如果 WebAssembly 不支持多线程,为什么第二个选项似乎适用于多线程?如果支持多线程,为什么第一个选项会阻塞UI?
@page "/asynctest"
<div class="row">
<div class="col">
@DisplayValue
</div>
<div class="col">
<button type="button" @onclick="OnClickFoo">Foo</button>
</div>
<div class="col">
<button type="button" @onclick="OnClickBar">Bar</button>
</div>
</div>
@code{
private string DisplayValue = "";
private double Result;
private async Task OnClickFoo(EventArgs e)
{
DisplayValue = "Working...";
Result = await Task.Run(() => Frobnicate()); // Blocks UI thread
DisplayValue = Result.ToString();
}
private async Task OnClickBar(EventArgs e)
{
DisplayValue = "Working...";
Result = await FrobnicateAsync(); // Doesn't block UI thread
DisplayValue = Result.ToString();
}
private int Frobnicate()
{
Thread.Sleep(2000); // do some heavy work
return 42;
}
private async Task<int> FrobnicateAsync()
{
await Task.Delay(2000); // do some heavy work async
return 42;
}
}
据我所知,Blazor WASM 不支持多线程,你只能得到 1 个线程。
在“OnClickBar”方法中,您没有创建不同的线程。您正在使用 async/await 状态机,它 returns 控制调用线程。 Task.Delay(2000)
不会阻塞线程,如 Stack Overflow question
在“OnClickFoo”方法中,您正在调用 Task.Run,它会尝试创建一个后台线程 - 这在 WASM 中无法正常工作,因为您只有一个线程,所以当您调用 Thread.Sleep(2000);
- UI 线程正在休眠。
在此处了解有关线程的更多信息:Microsoft Docs - Threads
相关堆栈溢出