我有一些复杂的计算需要一段时间才能完成。(是的,我知道,客户端听起来可能不是执行它们的理想场所,但有充分的理由。)我希望页面随着计算的进行而更新结果。随着计算的进行,我可以让 UI 重新渲染,但不能正确更新结果。
请注意,计算本身并不是异步的,将它们包装起来Task.Run似乎没有帮助。这是演示问题的代码的简化版本:
@page "/AsyncTest"
<button type="button" class="btn btn-primary" @onclick="@(e => RunOnClick(e))">Run</button>
<br />
<div>Percent Complete = @PercentComplete %</div>
@code {
private int PercentComplete = 0;
private async Task RunOnClick(MouseEventArgs e) {
for (PercentComplete = 0; PercentComplete < 100; PercentComplete += 20) {
System.Console.WriteLine($"LongCalculation: PercentComplete = {PercentComplete}");
await Task.Run(() => Calculation()); // Does not work.
//await CalculationAsync(); // This works.
StateHasChanged();
}
}
private void Calculation() => System.Threading.Thread.Sleep(500);
private async Task CalculationAsync() => await Task.Delay(500); …Run Code Online (Sandbox Code Playgroud) 我目前正在尝试在 blazor WASM 中异步调用一个昂贵的方法,同时不阻塞 UI 线程。
根据这个问题的回答,这是不可能的。然而,这些可以追溯到几年前,根据WebAssembly 路线图,现代浏览器支持线程。
另外,我可以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 …Run Code Online (Sandbox Code Playgroud)