页面重新加载后 Blazor InvokeAsync 不再工作
Blazor InvokeAsync no longer working after page reload
我有一个 Blazor 页面(服务器端),它使用对 Azure 服务总线的异步调用来获取一些数据并将结果打印到页面。一开始一切正常。但是,如果用户重新加载页面,页面不会按预期重新呈现。
断点调试显示模型 is 已更新,并且对 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 does get called on each OnAfterRenderAsync; we ignore 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
}
如果您无法解开该处理程序,则说明它在错误的位置。
我有一个 Blazor 页面(服务器端),它使用对 Azure 服务总线的异步调用来获取一些数据并将结果打印到页面。一开始一切正常。但是,如果用户重新加载页面,页面不会按预期重新呈现。
断点调试显示模型 is 已更新,并且对 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 does get called on each OnAfterRenderAsync; we ignore 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
}
如果您无法解开该处理程序,则说明它在错误的位置。