Blazor 从内部NavigationManager.LocationChanged调用异步方法

Blazor 从内部NavigationManager.LocationChanged调用异步方法,blazor,blazor-client-side,Blazor,Blazor Client Side,我正在使用NavigationManager.LocationChanged捕获查询字符串。在获得查询字符串值之后,我将进行一个ajax调用,它是异步的。LocationChanged本身是一种同步方法,看起来没有异步版本的LocationChanged。当从LocationChanged内部调用async方法时,async方法设置的值落后一步 这是报告: @page "/investigate" @implements IDisposable @inject NavigationManager

我正在使用
NavigationManager.LocationChanged
捕获查询字符串。在获得查询字符串值之后,我将进行一个ajax调用,它是异步的。LocationChanged本身是一种同步方法,看起来没有异步版本的
LocationChanged
。当从LocationChanged内部调用async方法时,async方法设置的值落后一步

这是报告:

@page "/investigate"
@implements IDisposable
@inject NavigationManager NM

<h1>Sync: @SyncValue</h1>
<h1>Async: @AsyncValue</h1>
<button @onclick="TriggerLocationChange">Increment</button>

@code {
    private string SyncValue;
    private string AsyncValue;
    private int Counter = 1;

    protected override void OnInitialized()
    {
        NM.LocationChanged += OnLocationChanged;
    }

    public void Dispose()
    {
        NM.LocationChanged -= OnLocationChanged;
    }

    private void OnLocationChanged(object sender, LocationChangedEventArgs args)
    {
        // sync action, just for comparison
        SyncValue = (Counter * 1000).ToString();

        DoSomeAsync();
    }

    private async Task DoSomeAsync()
    {
        // http call to server
        await Task.Delay(1);

        AsyncValue = (Counter * 1000).ToString();
    }

    private void TriggerLocationChange()
    {
        Counter++;
        NM.NavigateTo("investigate?counter=" + Counter);
    }
}
@page/“调查”
@实现IDisposable
@注入导航管理器NM
Sync:@SyncValue
Async:@AsyncValue
增量
@代码{
私有字符串同步值;
私有字符串值;
专用整数计数器=1;
受保护的覆盖无效OnInitialized()
{
NM.LocationChanged+=OnLocationChanged;
}
公共空间处置()
{
NM.LocationChanged-=OnLocationChanged;
}
私有void OnLocationChanged(对象发送方,LocationChangedEventArgs参数)
{
//同步操作,仅用于比较
SyncValue=(计数器*1000).ToString();
DoSomeAsync();
}
专用异步任务DoSomeAsync()
{
//对服务器的http调用
等待任务。延迟(1);
AsyncValue=(计数器*1000).ToString();
}
私有void TriggerLocationChange()
{
计数器++;
NM.NavigateTo(“调查?计数器=“+计数器”);
}
}
@AsyncValue
@SyncValue
落后一步


当从内部LocationChanged调用异步方法时,如何防止该方法落后?

使用异步标记方法不会更改该方法的签名,因此您应该这样做:

private async void OnLocationChanged(object sender, LocationChangedEventArgs args)
{
   // sync action:
   SyncValue = (Counter * 1000).ToString();

   await DoSomeAsync();
   StateHasChanged();
}


经过反复试验,我发现:

  • 当LocationChanged运行时,尚未设置管线参数值。这在我上面的例子中没有显示,但在我的例子中很重要。路由参数可以从URL手动提取,或者我们可以等到blazor使用
    wait Task.Delay(1)
    填充路由参数

  • 在异步方法的末尾调用
    statehaschange()

  • 我们应该用
    base.InvokeAsync(()=>…)

  • 经过这些修改后,OnLocationChanged变为:

    private void OnLocationChanged(对象发送方,LocationChangedEventArgs参数)
    {
    // ...
    base.InvokeAsync(异步()=>
    {
    wait Task.Delay(1);//等待blazor填充路由参数
    等待DoSomeAsync();
    StateHasChanged();
    });
    }
    
    您是否尝试使计数器静止<代码>专用整数计数器=1每次加载页面后,此选项将始终设置为1。关闭。您缺少一个
    statehaschange()
    等待DoSomeAsync()之后