Page 1 of 3

need help winform RequestContext/share render process

PostPosted: Fri Jun 04, 2021 10:54 am
by nhatnm
Hi! I'm new, I'm self learning control CEF on Winform. I'm trouble at render process when make browsers on multi-tabs. When main render process got heavy load, all browsers got laggy. That's why I want each tab will have each main render process for reduce laggy. I had read alot guides and I know can solve my trouble with RequestContext. But I had confused because in that guides make many things I didn't understand. Someone please help me a simple example for me learn? Please don't throw guides to anymore, the point they having many things I don't need and make me confuse.
Here's my simple test (CefSharp Winform 86.0.241)
Code: Select all
using System;
using System.Windows.Forms;
using CefSharp;
using CefSharp.WinForms;
using System.IO;
using System.Threading.Tasks;

namespace Test1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            InitializeChromium();
        }
        private void Form1_Load(object sender, EventArgs e)
        {

        }
        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            Cef.Shutdown();
        }

        public ChromiumWebBrowser browser, browser2;       
        public void InitializeChromium()
        {
            try
            {
                InitializeComponent();
                if (!Cef.IsInitialized)
                {
                    var cache_path = Path.Combine(Directory.GetCurrentDirectory(), @"cache");
                    CefSettings settings = new CefSettings()
                    {
                        CachePath = cache_path,
                        UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.241 Safari/537.36",
                        WindowlessRenderingEnabled = true,
                        MultiThreadedMessageLoop = true,
                        BrowserSubprocessPath = Path.Combine(Directory.GetCurrentDirectory(), @"CefSharp.BrowserSubprocess.exe")
                    };
                    settings.CefCommandLineArgs.Add("in-process-gpu", "1");
                    settings.CefCommandLineArgs.Add("enable-gpu", "1");
                    settings.CefCommandLineArgs.Add("enable-begin-frame-scheduling", "1");
                    settings.CefCommandLineArgs.Add("use-angle", "d3d11");
                    settings.CefCommandLineArgs.Add("enable-gpu-rasterization");
                    settings.CefCommandLineArgs.Add("process-per-tab");
                    settings.CefCommandLineArgs.Add("renderer-process-limit", "2");
                    Cef.EnableHighDPISupport();
                    CefSharpSettings.WcfEnabled = false;
                    Cef.Initialize(settings, performDependencyCheck: true, browserProcessHandler: null);
                    CefSharpSettings.LegacyJavascriptBindingEnabled = true;
                }
                string link = "https://www.google.com";
                browser = new ChromiumWebBrowser(link)
                {
                    BrowserSettings =
                {
                    Javascript = CefState.Enabled,
                    WindowlessFrameRate = 60
                }
                };
                this.Controls.Add(browser);     
                browser.Dock = DockStyle.Fill;               
                browser.FrameLoadEnd += Browser_FrameLoadEnd;
            }
            catch (Exception ex)
            {
                throw;
            }
        }
        private async void Browser_FrameLoadEnd(object sender, CefSharp.FrameLoadEndEventArgs e)
        {
            if (e.Frame.IsMain)
            {
                var html = await browser.GetSourceAsync();
                string google = "google.com";               
                if (html.Contains(google))
                {
                    var cefBrowser = browser.GetBrowser();
                    cefBrowser.StopLoad();
                    int numTabs = 3;                   
                    TabPage tab = new TabPage();                   
                    for (int i = 0; i < numTabs; i++)
                    {                       
                        IAsyncResult result = tabControl.BeginInvoke((MethodInvoker)async delegate
                        {
                            if (!tabControl.Visible) tabControl.Visible = true;
                            tab.Text = "Test";
                            string link2 = "https://www.bing.com/";
                            browser2 = new ChromiumWebBrowser(link2)
                            {
                                BrowserSettings =
                            {
                                Javascript = CefState.Enabled,
                                WindowlessFrameRate = 60
                            }
                            };                           
                            tabControl.Controls.Add(tab);
                            if (tabControl.TabCount == 0)
                            {
                                browser2.Parent = tabControl.SelectedTab;
                            }
                            else
                            {
                                tabControl.SelectTab(tabControl.TabCount - 1);
                                browser2.Parent = tabControl.SelectedTab;
                            }
                            tabControl.CreateControl();                           
                            browser2.Dock = DockStyle.Fill;                           
                        });
                        tabControl.EndInvoke(result);
                        await LoadPageAsync(browser2);
                    }
                }
            }           
        }
        public static Task LoadPageAsync(IWebBrowser browser, string address = null)
        {
            var tcs = new TaskCompletionSource<bool>(TaskCreationOptions.RunContinuationsAsynchronously);

            EventHandler<LoadingStateChangedEventArgs> handler = null;
            handler = (sender, args) =>
            {               
                if (!args.IsLoading)
                {
                    browser.LoadingStateChanged -= handler;                   
                    tcs.TrySetResult(true);
                }
            };
            browser.LoadingStateChanged += handler;
            if (!string.IsNullOrEmpty(address))
            {
                browser.Load(address);
            }
            return tcs.Task;
        }
    }
}


plus: not important, someone can tell me why LoadPageAsync in my test isn't work fine?

Re: need help winform RequestContext/share render process

PostPosted: Fri Jun 04, 2021 2:20 pm
by amaitland
Using renderer-process-limit is not supported, limiting the number of render processes will cause you problems. Using process-per-tab is also not supported, neither is in process GPU.

You seem to have used a random set of arguments and config options, WindowlessRenderingEnabled should only be used for WPF/OffScreen. enable-begin-frame-scheduling also is for WPF/OffScreen.

These arguments are more likely the cause of your problem.

As for your LoadPageAsync method I'd suggest creating a very simple example to test your code in isolation. You can use https://github.com/cefsharp/CefSharp.MinimalExample

Bing and Google will by default always use a different render process, using a RequestContext will not change the behaviour.

Your performance issues are likely of your own making.

Version 86 is old and unsupported, version 90 is the current supported version.

Re: need help winform RequestContext/share render process

PostPosted: Fri Jun 04, 2021 2:31 pm
by amaitland
Also if you are having problems understand a piece of documentation start by quoting the specific piece and asking for clarification. Just saying you don't understand and it's confusing doesn't allow for meaningful feedback.

Re: need help winform RequestContext/share render process

PostPosted: Fri Jun 04, 2021 3:41 pm
by nhatnm
Thanks for your reply! Ignore the sub-problems, I'm just testing from many guides I had found on google. My main point at about render process
When I'm try load my game (online) on first tab, everything is ok, 60 fps
1.png
1.png (354.65 KiB) Viewed 6346 times

But when I'm try load my game on my game on second tab, it got heavy, both tabs drop down around 20-30 fps
2.png
2.png (372.61 KiB) Viewed 6346 times

I had tested my game with SharpBrowser, both tabs is work fine with 60 fps. But I see it have share render process not like as me
3.png
3.png (283.78 KiB) Viewed 6346 times

that's why I think make share render process is possible. Search with days, I see pepole say around requestcontext for make this.
But when I try do something like as "browser.requestcontext = new requestcontext();", I see the browser just have clean up, main render process still not change. Did I missed something need do more than?
Sorry I'm new and my english isn't good

Re: need help winform RequestContext/share render process

PostPosted: Fri Jun 04, 2021 4:22 pm
by amaitland
The difference in performance is basically tied to the version. You are likely comparing two different versions.

As the sharpbrowser project is open source you can look at how they create the ChromiumWebBrowser instances and the settings passed to Cef.Initialize as a reference.

A RequestContext can be used to isolate sites of the same origin, sites of different origins will always use different render process.

Re: need help winform RequestContext/share render process

PostPosted: Fri Jun 04, 2021 6:40 pm
by nhatnm
of couse I had tried same same with its version 89 and only tested with my game. Now I'm trying around with other guides
I'm also look its source codes, but it have many things and many links, it's make hard for a newbie like as me
RequestContext is just my think, maybe I'm wrong, my point is share render process. Tried a week for find solution but I can't solve it, that's why I must find help at here
If you are not bothered, please give me a simple idea or example for share render process solution

Re: need help winform RequestContext/share render process

PostPosted: Fri Jun 04, 2021 7:07 pm
by amaitland
So you have a working reference in SharpBrowser, so let's start there. Does SharpBrowser use a RequestContext to isolate it's ChromiumWebBrowser instances?

I've you tried removing all the command line args/settings except CachePath? You've got a mess of unsupported options that you are using.

Re: need help winform RequestContext/share render process

PostPosted: Fri Jun 04, 2021 7:08 pm
by amaitland
The official documentation for RequestContext is at https://github.com/cefsharp/CefSharp/wi ... -isolation

If you have a particularly piece of wording that's unclear then please quote that working and ask for clarification.

Re: need help winform RequestContext/share render process

PostPosted: Fri Jun 04, 2021 7:14 pm
by amaitland
A quick search of the SharpBrowser src the only RequestContext example I can see is part of an xml file (someone appears to have checked in the dlls).

https://github.com/sharpbrowser/SharpBr ... estContext

No indication that SharpBrowser actually uses a RequestContext.

The Cef.Initialize call only shows a few settings set https://github.com/sharpbrowser/SharpBr ... rm.cs#L176

Again, remove all the settings you've changed except CachePath.

Re: need help winform RequestContext/share render process

PostPosted: Fri Jun 04, 2021 7:29 pm
by amaitland
If you have two tabs with one tab active then potentially what you are seeing is Potentially what you are seeing is https://github.com/cefsharp/CefSharp/issues/2922

It's possible the difference between your application and SharpBrowser is how the tabs behave, they appear to be using some form of custom BrowserTabStrip