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

WPF中WebView2 PrintAsync经Dispatcher调用打印空白PDF问题

WebView2 PrintAsync 跨线程触发打印空白PDF问题解决

问题核心

使用WebView2的PrintAsync()打印后台生成的PDF,绑定PDF生成完成的异步事件触发打印逻辑。由于事件可能在非UI线程触发,必须通过Dispatcher执行,但事件触发调用时,PrintAsync会瞬间返回,生成仅1页的空白PDF;而直接从UI线程(如按钮点击)调用则完全正常。

已尝试两种Dispatcher调用方式,均未解决问题:

// Version 1:InvokeAsync + Unwrap
private async Task printAll()
{
    CoreWebView2PrintStatus printStatus = CoreWebView2PrintStatus.OtherError;

    printStatus = await Dispatcher.InvokeAsync(async () =>
    {
        dummyWebView.Source = m_viewModel.renderedPdfForAllCalculations;
        return await dummyWebView.CoreWebView2.PrintAsync(m_printAllPrintSettings);
    }).Task.Unwrap();
    
    if (printStatus != CoreWebView2PrintStatus.Succeeded)
    {
        // 提示错误
    }
}

// Version 2:直接Invoke
private async Task printAll()
{
    CoreWebView2PrintStatus printStatus = CoreWebView2PrintStatus.OtherError;

    await Dispatcher.Invoke(async () =>
    {
        dummyWebView.Source = m_viewModel.renderedPdfForAllCalculations;
        printStatus = await dummyWebView.CoreWebView2.PrintAsync(m_printAllPrintSettings);
    });
    
    if (printStatus != CoreWebView2PrintStatus.Succeeded)
    {
        // 提示错误
    }
}

问题原因

两种写法都忽略了关键逻辑:设置dummyWebView.Source后,WebView2加载PDF是异步过程,直接紧接着调用PrintAsync时,PDF还未完成渲染,此时打印的是未加载完成的空白页面。

UI线程直接调用时,可能碰巧PDF已在缓存中,或加载速度快到感知不到延迟;但事件触发时(尤其是后台生成后刚触发),PDF是首次加载,必然存在加载延迟,导致打印空白。

解决方案

必须等待WebView2完全加载并渲染PDF后,再执行PrintAsync。通过监听CoreWebView2.NavigationCompleted事件实现是最可靠的方式。

修正后的代码示例

private async Task printAll()
{
    CoreWebView2PrintStatus printStatus = CoreWebView2PrintStatus.OtherError;

    await Dispatcher.InvokeAsync(async () =>
    {
        // 用TaskCompletionSource将事件回调转为可await的Task
        var loadCompletionTcs = new TaskCompletionSource<bool>();
        
        void NavigationCompletedHandler(object sender, CoreWebView2NavigationCompletedEventArgs e)
        {
            if (e.IsSuccess)
            {
                loadCompletionTcs.TrySetResult(true);
            }
            else
            {
                loadCompletionTcs.TrySetException(new Exception("PDF加载失败"));
            }
            // 移除事件监听,避免内存泄漏
            dummyWebView.CoreWebView2.NavigationCompleted -= NavigationCompletedHandler;
        }

        // 添加导航完成事件监听
        dummyWebView.CoreWebView2.NavigationCompleted += NavigationCompletedHandler;
        // 设置PDF源
        dummyWebView.Source = m_viewModel.renderedPdfForAllCalculations;

        try
        {
            // 等待PDF加载完成
            await loadCompletionTcs.Task;
            // 加载完成后执行打印
            printStatus = await dummyWebView.CoreWebView2.PrintAsync(m_printAllPrintSettings);
        }
        catch (Exception ex)
        {
            // 处理加载失败的情况
            printStatus = CoreWebView2PrintStatus.OtherError;
        }
    });

    if (printStatus != CoreWebView2PrintStatus.Succeeded)
    {
        // 显示错误提示
    }
}

关键说明

  1. 监听NavigationCompleted:确保PDF成功加载后再执行打印,彻底避免提前调用PrintAsync的问题。
  2. TaskCompletionSource转换:将事件回调逻辑转为异步Task,方便用await优雅等待加载完成。
  3. 移除事件监听:加载完成后及时移除事件处理程序,防止内存泄漏。
  4. 异常捕获:处理PDF加载失败的场景,避免未捕获异常影响程序运行。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 15:52:48