Search code examples
c#cefsharpcefsharp.offscreen

CefSharp winfoms Page load and wait


I'm working on Cefsharp Offscreen in my application. The code provided in documentation to load page is:

 const string testUrl = "https://github.com/cefsharp/CefSharp/wiki/Quick-Start";
  var settings = new CefSettings()
        {
   //By default CefSharp will use an in-memory cache, you need to specify a Cache Folder to persist data
   CachePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "CefSharp\\Cache")
        };

   //Perform dependency check to make sure all relevant resources are in our output directory.
   Cef.Initialize(settings, performDependencyCheck: true, browserProcessHandler: null);

   // Create the offscreen Chromium browser.
   browser = new ChromiumWebBrowser(testUrl);

   // An event that is fired when the first page is finished loading.
   // This returns to us from another thread.
   browser.LoadingStateChanged += BrowserLoadingStateChanged;
   Cef.Shutdown();

but I want something like that

browser = new ChromiumWebBrowser(); //without testUrl
 // and then 
browser.Load(testUrl).Wait();// and wait something like that;
// load url and wait unit page is fully loaded then go to next line

I couldn't find any solution.


Solution

  • The CefSharp.OffScreen.Example.Program.cs class in the project source contains an example of using a TaskCompletionSource to wrap the LoadingStateChanged event so you can await the Page Load.

    A basic example implemented as an extension method would look like:

    public static class WebBrowserExtensions
    {
        public static Task LoadPageAsync(this IWebBrowser browser, string address = null)
        {
            var tcs = new TaskCompletionSource<bool>(TaskCreationOptions.RunContinuationsAsynchronously);
    
            EventHandler<LoadingStateChangedEventArgs> handler = null;
            handler = (sender, args) =>
            {
                //Wait for while page to finish loading not just the first frame
                if (!args.IsLoading)
                {
                    browser.LoadingStateChanged -= handler;
                    //Important that the continuation runs async using TaskCreationOptions.RunContinuationsAsynchronously
                    tcs.TrySetResult(true);
                }
            };
    
            browser.LoadingStateChanged += handler;
    
            if (!string.IsNullOrEmpty(address))
            {
                browser.Load(address);
            }
    
            return tcs.Task;
        }
    }
    

    You can then write code like

    browser = new ChromiumWebBrowser();
    await browser.LoadPageAsync(testUrl);
    

    The browser is written to be async and blocking using Task.Wait is not recommended nor supported. Use async/await.