页面重新加载后 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 
}

如果您无法解开该处理程序,则说明它在错误的位置。