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) { // 显示错误提示 } }
关键说明
- 监听NavigationCompleted:确保PDF成功加载后再执行打印,彻底避免提前调用
PrintAsync的问题。 - TaskCompletionSource转换:将事件回调逻辑转为异步Task,方便用
await优雅等待加载完成。 - 移除事件监听:加载完成后及时移除事件处理程序,防止内存泄漏。
- 异常捕获:处理PDF加载失败的场景,避免未捕获异常影响程序运行。
内容的提问来源于stack exchange,提问作者Tsaras
相关产品推荐
相关产品推荐

