You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

UWP WebView仅触发最后一次请求的NavigationCompleted事件,如何让每次都触发?

问题分析与解决方案

这个问题的核心原因很明确:WebView的导航操作是异步且排他的——当你在循环里连续调用NavigateToLocalStreamUri时,后一次的导航请求会立刻终止前一次还在进行中的导航流程。这就导致前两次的导航还没来得及完成,就被下一次请求打断了,自然不会触发NavigationCompleted事件,只有最后一次没有被打断的导航能走完完整流程,触发对应的完成事件。

要解决这个问题,你需要让导航操作串行执行:等待上一次导航完全完成(不管成功还是失败)后,再发起下一次导航请求。下面是具体的实现方案:

异步等待导航完成的实现

我们可以用TaskCompletionSource来包装NavigationCompleted(以及NavigationFailed)事件,把异步事件转换成可等待的Task,从而实现循环中的串行导航:

// 把循环改成异步方法
private async Task NavigateWithSequentialCompletion()
{
    for (int i = 0; i < 3; i++)
    {
        var tcs = new TaskCompletionSource<bool>();
        
        // 定义导航完成的事件处理程序
        void NavigationCompletedHandler(object sender, NavigationCompletedEventArgs e)
        {
            // 先取消订阅,避免内存泄漏
            _webView.NavigationCompleted -= NavigationCompletedHandler;
            _webView.NavigationFailed -= NavigationFailedHandler;
            tcs.SetResult(true);
        }
        
        // 定义导航失败的事件处理程序(可选但建议加上,避免任务永远等待)
        void NavigationFailedHandler(object sender, NavigationFailedEventArgs e)
        {
            _webView.NavigationCompleted -= NavigationCompletedHandler;
            _webView.NavigationFailed -= NavigationFailedHandler;
            // 可以根据需要抛出异常或者标记失败
            tcs.SetException(new InvalidOperationException($"导航失败: {e.WebErrorStatus}"));
        }
        
        // 订阅事件
        _webView.NavigationCompleted += NavigationCompletedHandler;
        _webView.NavigationFailed += NavigationFailedHandler;
        
        // 发起本次导航
        _webView.NavigateToLocalStreamUri(url[i], resolver);
        
        // 等待本次导航完成(成功或失败)
        await tcs.Task;
    }
}

方案说明

  1. 串行执行逻辑:通过await tcs.Task,我们强制循环在发起下一次导航前,等待当前导航的NavigationCompleted或NavigationFailed事件触发,确保每一次导航都能走完完整的生命周期。
  2. 事件清理:每次导航完成/失败后,立刻取消对事件的订阅,避免因为重复订阅导致的内存泄漏和重复触发问题。
  3. 异常处理:加入NavigationFailed的处理,防止因为导航出错导致TaskCompletionSource一直处于未完成状态,造成程序卡住。

调用这个异步方法时,记得在合适的地方用await,比如在按钮点击事件里:

private async void Button_Click(object sender, RoutedEventArgs e)
{
    await NavigateWithSequentialCompletion();
}

这样修改后,每一次循环的导航都会依次触发NavigationStarting和对应的NavigationCompleted(或NavigationFailed)事件,不会再出现前面的导航被打断的情况。

内容的提问来源于stack exchange,提问作者user2706

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 06:17:23