WebView2 中通过按钮点击网页元素调用 C# WinForm 的 ShowDialog() 导致程序崩溃

在 WebView2 中通过按钮点击调用 C WinForm 的 ShowDialog() 导致程序崩溃,通常与 UI 线程阻塞或 跨线程操作 有关。

window.chrome.webview.postMessage("openHistory", { sessionId: item.sessionId });


 问题原因分析
1. UI 线程阻塞:
    ShowDialog() 是模态对话框,会阻塞当前线程(通常是 UI 线程)。
    WebView2 依赖 UI 线程的消息循环处理异步事件(如 JavaScript 与 C 的通信)。若 UI 线程被阻塞,WebView2 可能无法正常处理内部消息,导致崩溃。

2. 跨线程操作:
    如果在非 UI 线程操作 WebView2 控件(如通过 Task.Run),可能违反线程安全规则,引发异常。

3. 资源释放问题:
    关闭对话框后,可能意外释放了 WebView2 相关资源(如 CoreWebView2 对象),导致后续操作崩溃。



 解决方案
 1. 确保在 UI 线程调用 ShowDialog()
    确保按钮点击事件在 UI 线程触发,避免跨线程调用。可通过 Invoke 方法强制在 UI 线程执行:
     csharp
     private void WebView2ButtonClickHandler(object sender, EventArgs e)
     {
         if (this.InvokeRequired)
         {
             this.Invoke(new Action(() => WebView2ButtonClickHandler(sender, e)));
             return;
         }
         using (var dialog = new YourForm())
         {
             dialog.ShowDialog();
         }
     }
     

 2. 改用非阻塞对话框(如 Show())
    如果业务允许,使用非模态窗体 Show(),避免阻塞 UI 线程:
     csharp
     dialog.Show(); // 非阻塞
     
    注意:需自行处理窗体关闭后的逻辑(如回调)。

 3. 检查异常和资源释放
    在 trycatch 块中调用 ShowDialog(),捕获未处理异常:
     csharp
     try
     {
         using (var dialog = new YourForm())
         {
             dialog.ShowDialog();
         }
     }
     catch (Exception ex)
     {
         Debug.WriteLine($"Exception: {ex}");
     }
     
    确保对话框关闭时未误释放 WebView2 资源(如 webView.Dispose())。

 4. 异步处理对话框
    使用 async/await 模拟非阻塞模态对话框,避免完全冻结 UI 线程:
     csharp
     private async void WebView2ButtonClickHandler(object sender, EventArgs e)
     {
         var dialog = new YourForm();
         await Task.Run(() => dialog.ShowDialog());
         // 关闭后的逻辑
     }
     
    注意:此方法可能因线程切换导致跨线程操作控件,需谨慎处理。

 5. 更新 WebView2 运行时和 SDK
    确保使用最新版本的 [WebView2 SDK](https://developer.microsoft.com/enus/microsoftedge/webview2/) 和运行时,修复已知兼容性问题。



 验证步骤
1. 最小化复现:创建一个仅包含 WebView2 和按钮的简单 WinForm 项目,点击按钮弹出 ShowDialog(),观察是否崩溃。
2. 日志调试:在 AppDomain.CurrentDomain.UnhandledException 中记录全局异常,或在调试器中捕获异常堆栈。
3. 进程检查:关闭对话框后,检查任务管理器是否有残留进程,确认是否为资源泄漏。



 总结
根本原因在于 ShowDialog() 阻塞了 UI 线程,导致 WebView2 消息泵无法处理事件。解决方案需确保 WebView2 的线程通信不受阻塞,或通过异步/线程安全方式操作对话框。

猜你喜欢

转载自blog.csdn.net/nbspzs/article/details/147049698
今日推荐