我是Blazor的新手。我正在开发一个服务器应用程序(而不是WASM(。
在页面加载中,我将两件事加载到一个页面。第1项通过API调用与第2项同时加载。我希望个别商品一有货就立即出现。我在想类似的东西
protected override async Task OnInitializedAsync()
{
var t1 = _service.GetItem1().ContinueWith(t => {
Item1Loaded = true;
Item2State = t.Result;
await InvokeAsync(StateHasChanged);
});
var t2 = _service.GetItem2().ContinueWith(t => {
Item2Loaded = true;
Item2State = t.Result;
await InvokeAsync(StateHasChanged);
});
}
不过,我对此有几个问题:
- 如果用户离开组件,我需要担心取消这些行吗?(移除组件后更改状态变量会导致问题吗(还是Blazor在框架级别以某种方式处理了这个问题
- 我需要确保它返回到具有同步上下文的某个线程吗?似乎
InvokeAsync
只是为我做这件事,但想确定一下 - CCD_ 2的现代例子不多见。async/await占主导地位,但我认为它不允许继续按完成的顺序执行。这是合理的使用吗
由于您使用的是服务器端,因此可以更干净地完成此操作(ContinueWith或多或少已经过时,因为async/await(:
protected override async Task OnInitializedAsync()
{
var t1 = Task.Run(async () =>
{ Item1State = await _service.GetItem1();
Item1Loaded = true; // you can probably derive this from Item1State
await InvokeAsync(StateHasChanged);
});
var t2 = Task.Run(async () =>
{ Item2State = await _service.GetItem2();
Item2Loaded = true;
await InvokeAsync(StateHasChanged);
});
await Task.WhenAll(t1, t2);
}
无需在此处调用StateHasChanged((
如果没有ItemLoaded保护,您可以在没有Task.Run((.的情况下完成此操作
如果用户离开,我需要担心取消这些行吗
大多数现代DB内容都可以传递取消令牌。因此,如果您想取消操作,请使用它。如果这是您自己的代码,并且操作是长期运行的,请考虑使用取消令牌。
我需要确保它返回到具有同步上下文的某个线程吗?
调用await InvokeAsync(StateHasChanged);
可确保UI代码在UI线程上运行。
问题3
坚持使用简单的await
。是的,它按顺序执行。如果有两个以上的等待操作,则在操作之间调用await InvokeAsync(StateHasChanged)
以更新UI。
注意:只有当您等待真正的异步代码,而不是任务中的同步代码时,这才会起作用!如果没有收益,则渲染器没有线程时间,因此UI在获得一些收益之前不会得到更新。