8

As per Microsoft's Getting Started with webView2 in Windows Forms (as of 2021 March 9), I've got the following code (with webView2.source not set; edited out of Form.Designer.cs):

    public Form1() {
      InitializeComponent();
      InitializeAsync();
    }

    async void InitializeAsync() {
      Console.WriteLine("InitializeAsync starting");
      await webView2.EnsureCoreWebView2Async(null);
      Console.WriteLine("InitializeAsync done");
    }

    private void Form1_Load(object sender, EventArgs e) {
      Console.WriteLine("Load event");
    }

    private void webView2_CoreWebView2InitializationCompleted(object sender, CoreWebView2InitializationCompletedEventArgs e) {
      Console.WriteLine("CoreWebView2InitializationCompleted event");
      if ((webView2 == null) || (webView2.CoreWebView2 == null))
        Console.WriteLine("not ready");
      webView2.NavigateToString(File.ReadAllText("index.html"));
    }

I'm surprised to get an exception at the NavigateToString():

System.InvalidOperationException
  HResult=0x80131509
  Message=The instance of CoreWebView2 is uninitialized and unable to complete this operation. See InitializeAsync.
  Source=Microsoft.Web.WebView2.WinForms
  StackTrace:
   at Microsoft.Web.WebView2.WinForms.WebView2.VerifyInitializedGuard()
   at Microsoft.Web.WebView2.WinForms.WebView2.NavigateToString(String htmlContent)
   at webview2_base.Form1.webView2_CoreWebView2InitializationCompleted(Object sender, CoreWebView2InitializationCompletedEventArgs e) in E:\Visual Studio 2019\source\repos\explore\webview2_base\Form1.cs:line 37
   at Microsoft.Web.WebView2.WinForms.WebView2.<InitCoreWebView2Async>d__13.MoveNext()

The console output is:

InitializeAsync starting
Load event
CoreWebView2InitializationCompleted event
Exception thrown: 'System.InvalidOperationException' in Microsoft.Web.WebView2.WinForms.dll
An exception of type 'System.InvalidOperationException' occurred in Microsoft.Web.WebView2.WinForms.dll but was not handled in user code
The instance of CoreWebView2 is uninitialized and unable to complete this operation. See InitializeAsync.

What's up with that? I would have thought CoreWebView2 would have completed its initialization, given the label of the event.

The code works if the Navigate is moved to after the 'await' in InitializeAsync. I probably don't understand 'await', I thought it would delay the completion of the Form constructor, and the Load event, until after CoreWebView2 completed.

I'd like to put the Navigate in the Form Load event handler (but it fires before CoreWebView2 is ready).

Am I not understanding something, or is there a bug here relating to CoreWebView2 not being initialized even after it's 'initializeComplete' event has fired?

VS2019 16.9, Net 4.7.2, webview2 version 91.0.823.0 canary

Update (2021-03-19): It works if 'webView2.NavigateToString()' is replaced with 'webView2.CoreWebView2.NavigateToString()'. But given the event name, it seems either should work at that point.

Baffin
  • 132
  • 1
  • 1
  • 6
  • 4
    Move `await webView2.EnsureCoreWebView2Async();` to `Form.Load` and make the handler `async`. – Jimi Mar 09 '21 at 16:28
  • When you call an `async void` method, it's actually 'fire and forget'. It doesn't `await` the call, but continues right away. – Poul Bak Mar 09 '21 at 17:40

1 Answers1

9

You need to use await InitializeAsync(); which means async void InitializeAsync should be async Task InitializeAsync. Since async can't be used with a constructor, you'll have to call InitializeAsync from Form1_Load.

Try the following:

using System.Diagnostics;

Option 1:

public Form1()
{
    InitializeComponent();
}

private async void Form1_Load(object sender, EventArgs e)
{
    webView2.CoreWebView2InitializationCompleted += WebView_CoreWebView2InitializationCompleted;

    Debug.WriteLine("before InitializeAsync");
    await InitializeAsync();
    Debug.WriteLine("after InitializeAsync");

    //webView2.CoreWebView2.Navigate("https://www.microsoft.com");
    //Debug.WriteLine("after Navigate");

    if ((webView2 == null) || (webView2.CoreWebView2 == null))
    {
        Debug.WriteLine("not ready");
    }

    webView2.NavigateToString(System.IO.File.ReadAllText("index.html"));

    Debug.WriteLine("after NavigateToString");
}

private async Task InitializeAsync()
{
    Debug.WriteLine("InitializeAsync");
    await webView2.EnsureCoreWebView2Async(null);
    Debug.WriteLine("WebView2 Runtime version: " + webView2.CoreWebView2.Environment.BrowserVersionString);
}


private void WebView_CoreWebView2InitializationCompleted(object sender, Microsoft.Web.WebView2.Core.CoreWebView2InitializationCompletedEventArgs e)
{
    Debug.WriteLine("WebView_CoreWebView2InitializationCompleted");
}

Output:

before InitializeAsync
InitializeAsync
WebView_CoreWebView2InitializationCompleted
WebView2 Runtime version: 89.0.774.48
after InitializeAsync
after NavigateToString

Update - here's another option

Option 2:

public Form1()
{
    InitializeComponent();
}

private async void Form1_Load(object sender, EventArgs e)
{
    webView2.CoreWebView2InitializationCompleted += WebView_CoreWebView2InitializationCompleted;

    Debug.WriteLine("before InitializeAsync");
    await InitializeAsync();
    Debug.WriteLine("after InitializeAsync");

}

private async Task InitializeAsync()
{
    Debug.WriteLine("InitializeAsync");
    await webView2.EnsureCoreWebView2Async(null);
    Debug.WriteLine("WebView2 Runtime version: " + webView2.CoreWebView2.Environment.BrowserVersionString);

    //webView2.CoreWebView2.Navigate("https://www.microsoft.com");
    //Debug.WriteLine("after Navigate");

    if ((webView2 == null) || (webView2.CoreWebView2 == null))
    {
        Debug.WriteLine("not ready");
    }

    webView2.NavigateToString(System.IO.File.ReadAllText("index.html"));

    Debug.WriteLine("after NavigateToString");
}


private void WebView_CoreWebView2InitializationCompleted(object sender, Microsoft.Web.WebView2.Core.CoreWebView2InitializationCompletedEventArgs e)
{
    Debug.WriteLine("WebView_CoreWebView2InitializationCompleted");
}

Output:

before InitializeAsync
InitializeAsync
WebView_CoreWebView2InitializationCompleted
WebView2 Runtime version: 89.0.774.48
after NavigateToString
after InitializeAsync
Tu deschizi eu inchid
  • 4,117
  • 3
  • 13
  • 24
  • Thanks, that nicely accomplishes moving the Navigate to Form1_Load. However, it doesn't answer why a 'not yet initialized' exception is raised in the 'initializationComplete' event handler (when seemingly initialization ought to be complete). Is this a Microsoft bug (or at least a naming and doc problem)? – Baffin Mar 09 '21 at 21:40
  • At one point the method was `CoreWebView2Ready`. The public method was changed to `CoreWebView2InitializationCompleted`. A while back I found that initialization may not be complete until after the method returns. I decided not to place any code inside these methods except for subscribing to additional event handlers. – Tu deschizi eu inchid Mar 09 '21 at 22:19
  • I thought that the WebView2 control should be ready to use once `CoreWebView2InitializationCompleted` was entered too--not after it returns from the method. To get the desired behavior, I moved my code around as shown above. WebView2 is still in development, so you can submit your ideas here: https://github.com/MicrosoftEdge/WebView2Feedback/issues – Tu deschizi eu inchid Mar 09 '21 at 22:49
  • I added another option which reduces the amount of code in Form1_Load. – Tu deschizi eu inchid Mar 09 '21 at 23:05
  • 1
    @user9938 Thanks for helping me fix a problem where my app ran fine on one PC, threw a WebView2 exception on another. IMO WebView2 is needlessly complicated. I know it's based on Chrome, and maybe MS programmers don't understand it enough to streamline its operation and interface. I just wish it was as simple to use as original WebView. – Skyfish Apr 09 '22 at 17:21
  • 2
    @Skyfish I couldn't agree more. It's overblown and reeks of developer over-development. At least the option of an update to the simpler and light-weight `WebBrowser` control would have been all I would ever need. Instead it's hours/days of messing about with this or third-party solutions. – SteveCinq Jul 29 '22 at 01:44