我有一个Blazor页面(服务器端(,它使用对Azure服务总线的异步调用来获取一些数据并将结果打印到页面上。一开始一切都很好。但是,如果用户重新加载页面,则页面不会按预期重新呈现。
使用断点进行调试表明,模型被更新,并且在页面重载后执行对StateHasChanged
的调用;它根本没有任何作用。我的印象是InvokeAsync
应该总是使用UI线程,但在页面重新加载后,情况似乎并非如此。
protected override async Task OnAfterRenderAsync(bool firstRender)
{
// On page load. Service bus watcher is hooked up here
await serviceBusHandler.WatchQueue("servicebus-queue", MessageHandler, async _ => await Task.CompletedTask);
}
// "request" method; calls a Service Bus method get a new value for our model
private async Task SaveAndGetAmount()
{
IsLoading = true;
// creation of Service Bus message omitted
// post to "servicebus-queue" with message here
}
private async Task MessageHandler(ProcessSessionMessageEventArgs args)
{
var result = ... // parsing of "args" message omitted
await args.CompleteMessageAsync(args.Message); // mark Azure Functions message received
await InvokeAsync(() =>
{
IsLoading = false;
Model.Amount = result.Amount; // update page model here
StateHasChanged(); // indicate to UI that the model has changed, and the page must re-render
});
此外,我在Model.Amount
属性中添加了一块手表,它显示出一些奇怪的行为。如果在初始页面加载时设置为23,则在SaveAndGetAmount
方法中,监视将始终在我的断点上显示23,就好像MessageHandler
方法从未更新过它一样。
WatchQueue在每个OnAfterRenderAsync上都会被调用;我们忽略firstRender
protected override async Task OnAfterRenderAsync(bool firstRender)
{
// On page load. Service bus watcher is hooked up here
await serviceBusHandler.WatchQueue("servicebus-queue", MessageHandler, async _ => await Task.CompletedTask);
}
这里只是猜测,但这意味着每个(重新(渲染都会添加一个消息处理程序。这是错误的,但只要你在页面的同一个实例上,就不会被注意到。
重新加载后,您的消息仍在旧的(已失效的(页面上处理。这就是我认为您在调试器中看到的情况。
如果我是对的,解决方案有两个方面:
@implements IDisposable
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender) // only once per page
{
// On page load. Service bus watcher is hooked up here
await serviceBusHandler.WatchQueue("servicebus-queue", MessageHandler, async _ => await Task.CompletedTask);
}
}
public void Dispose()
{
// somehow undo the WatchQueue
}
如果你不能解开处理程序,那么它就在错误的地方。