0

I'm trying to use an embedded WebView2 control in my WPF application, and open an Ookii VistaSaveFileDialog in response to communication from the webview.

However, once I've run the dialog's ShowDialog method (which blocks while waiting for a user response) and the dialog is open, the app suddenly shuts down with no exception or warning. This happens intermittently.

It only seems to happen when I've run the code in Debug mode, debugging with VS. Release mode doesn't seem to have this problem.

Deleting the bin and obj folders and rebuilding the solution doesn't help.

How can I go about debugging/resolving this?

Target/version info: TFM: net6.0-windows
WebView2: 1.0.1210.39
Ookii.Dialogs.Wpf: 5.0.1

XAML:

<Window x:Class="_testWebviewDialogs.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:wv="clr-namespace:Microsoft.Web.WebView2.Wpf;assembly=Microsoft.Web.WebView2.Wpf">
    <wv:WebView2 x:Name="webview" Source="about:blank"/>
</Window>

Code-behind:

using Ookii.Dialogs.Wpf;
using System.IO;
using System.Windows;

namespace _testWebviewDialogs;
public partial class MainWindow : Window {
    public MainWindow() {
        InitializeComponent();
        initializeAsync();
    }

    private async void initializeAsync() {
        await webview.EnsureCoreWebView2Async();
        var html = await File.ReadAllTextAsync("container.html");
        webview.NavigateToString(html);
        webview.CoreWebView2.WebMessageReceived += (s, e) => {
            var dlg = new VistaSaveFileDialog();
            dlg.ShowDialog(); // Sometimes the app shuts down while in this (blocking) call
            MessageBox.Show(dlg.FileName);
            webview.CoreWebView2.PostWebMessageAsString(dlg.FileName);
        };
    }
}

container.html, which is copied to the output folder:

<!DOCTYPE html>
<html>
<body>
    <button id="button1">Click me</button>
    <script>
        document.getElementById('button1')
            .addEventListener('click', ev => {
                chrome.webview.postMessage('Hello from webview');
            });
    </script>
</body>
</html>
Zev Spitz
  • 13,950
  • 6
  • 64
  • 136
  • As a note, initializeAsync should be awaitable, i.e. declared as `private async Task InitializeAsync()` and it should be awaited, e.g. in an async Loaded evnt handler like `Loaded += async (s, e) => await InitializeAsync();` – Clemens May 12 '22 at 06:16
  • @Clemens The problem still occurs after changing to a `Task` returning method. I would add that [this is how its done in the docs](https://learn.microsoft.com/en-us/microsoft-edge/webview2/get-started/wpf#step-9---communication-between-host-and-web-content). – Zev Spitz May 12 '22 at 08:55
  • It was meant as a note, not a solution. And that is a bad example in the documentation. The general rule is that every async method should be awaited, except event handlers. – Clemens May 12 '22 at 09:02

1 Answers1

0

Per the suggestion I received on the GitHub issue I filed, the following seems to work:

webview.CoreWebView2.WebMessageReceived += (s, e) => 
    SynchronizationContext.Current!.Post((_) => {
        var dlg = new VistaSaveFileDialog();
        dlg.ShowDialog();
        MessageBox.Show(dlg.FileName);
        webview.CoreWebView2.PostWebMessageAsString(dlg.FileName);
    }, null);

Source: Threading model for WebView2 apps: Reentrancy

Zev Spitz
  • 13,950
  • 6
  • 64
  • 136