CEFSharp 应用程序显示空白屏幕,然后在一分钟后自行响应

CEFSharp app displays blank screen and then responds on it's own after a minute

我一直在开发一个应用程序,它使用 CEFSharp(版本 83.4.20)加载我公司的 VOIP 平台(engage.ringcentral.com)。来源在 Github https://github.com/dylanlangston/EngageRC

该应用程序已经运行了大约一个月,在将其投入生产后,我收到了一个奇怪问题的报告。人们看到的是空白屏幕,无法与网页交互( Example of issue)。几分钟后,问题似乎自行解决,并且他们能够再次与网页进行交互。我自己无法重现该问题。

我认为这可能是渲染问题。到目前为止,我已经尝试在我的应用程序中调整以下内容:

删除下面的行。

settings.CefCommandLineArgs.Add("disable-gpu");
settings.CefCommandLineArgs.Add("disable-gpu-shader-disk-cache", "1");

将它们替换为。

settings.CefCommandLineArgs.Add("disable-gpu-compositing");

不幸的是,这并没有解决问题,我不确定我遗漏了什么。

CEF Initialization的相关代码位于InitializeChromium方法下的https://github.com/dylanlangston/EngageRC/blob/master/Windows/MainWindow.Designer.cs。见下文

    // 
    // Chrome
    // 
    private CefSharp.WinForms.ChromiumWebBrowser chromeBrowser;
    public ChromiumWebBrowser InitializeChromium(string URL, string Name)
    {
        // Check if already Initialized
        if (Cef.IsInitialized == false)
        {
            CefSettings settings = new CefSettings();
            // Enable Logging if debugging or console window
            if (!this.debug || !this.console)
            {
                settings.LogSeverity = LogSeverity.Disable;
            }
            else
            {
                settings.LogSeverity = LogSeverity.Verbose;
            }
            // Enable Microphone settings
            settings.CefCommandLineArgs.Add("enable-media-stream", "1");
            // Set Custom Browser Paths
            settings.CefCommandLineArgs.Add("disable-gpu-shader-disk-cache", "1");
            // Disable GPU to fix rendering issues on some machines.
            settings.CefCommandLineArgs.Add("disable-gpu");
            // Disable CORS protection (cross site scripting) which the engage.ringcentral.com site doesn't seem to like/respect, disabled as the website doesn't seem to improve with this turned on.
            //settings.CefCommandLineArgs.Add("disable-web-security");
            // Enable session Cookie persistence, disabled as it's unneeded. 
            //settings.PersistSessionCookies = true;
            // Custom Browser paths
            settings.BrowserSubprocessPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, @"Resources\CEFSharp\CefSharp.BrowserSubprocess.exe");
            settings.LocalesDirPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, @"Resources\CEFSharp\locales\");
            settings.ResourcesDirPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, @"Resources\CEFSharp\");
            // Check if Resources folder is writable. If it isn't then write to application data.
            DirectoryInfo di = new DirectoryInfo(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, @"Resources\CEFSharp\"));
            if ((di.Attributes & FileAttributes.ReadOnly) == FileAttributes.ReadOnly)
            {
                settings.RootCachePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), @"EngageRC\CEFSharp\cache");
                settings.CachePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), @"EngageRC\CEFSharp\cache");
                settings.LogFile = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), @"EngageRC\CEFSharp\debug.log");
            }
            else
            {
                settings.RootCachePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, @"Resources\CEFSharp\cache");
                settings.CachePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, @"Resources\CEFSharp\cache");
                settings.LogFile = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, @"Resources\CEFSharp\debug.log");
            }
            // Initialize cef with the provided settings or add new tab
            Cef.Initialize(settings, performDependencyCheck: true, browserProcessHandler: null);
        }
        // Create a browser component
        chromeBrowser = new ChromiumWebBrowser(URL);
        // Set Name
        chromeBrowser.Name = Name;
        // Adjust size and scaling
        this.chromeBrowser.Dock = DockStyle.Fill;
        this.chromeBrowser.Width = this.Width;
        this.chromeBrowser.Height = this.Height;
        // Add control
        this.Controls.Add(chromeBrowser);
        // Bring to front
        this.chromeBrowser.BringToFront();
        // Set label to Goodbye.
        this.label1.Text = "Goodbye";

        // Return control
        return chromeBrowser;
    }

我无法找到我的 Google foo 之前的任何问题,所以这似乎不是其他人看到的他们的应用程序。关于 C#,我仍在学习中,所以这 100% 可能是我自己的错,我做错了什么。

我能够从遇到问题的机器上获得详细的日志记录。我主要看到以下错误。 https://gist.github.com/dylanlangston/194e389ead437e6c6fe08b2d4746bf43

处的完整日志

[0729/083616.491:ERROR:paint_controller.cc(646)] PaintController::FinishCycle() completed

感谢任何有助于解决此问题的想法或建议!


更新: 根据@amaitland 的有用评论,似乎这种行为可能是由于在我不应该的线程上使用 Thread.Sleep 引起的。

查看我的代码后,我发现我在两个位置都有这个。

首先,我调用 thread.sleep 等待浏览器缩放级别与我保存到 windows 独立存储的值相匹配。这不应该 运行ning 除非应用程序首次启动。我不认为这是问题所在,但为了安全起见,我还是将其发布在这里。 (https://github.com/dylanlangston/EngageRC/blob/master/CEFSharpHandlers.cs)

public void OnLoadingStateChanged(object sender, LoadingStateChangedEventArgs args)
        {
            ChromiumWebBrowser chrome = (ChromiumWebBrowser)sender;
            if (!args.IsLoading) // Loading finished.
            {
                // If first load set zoom level to previous level
                if (firstLoad < 3)
                {
                    try
                    {
                        double zoom = double.Parse(ConfigReader.ReadIsolatedStorage("z"), System.Globalization.CultureInfo.InvariantCulture);
                        while (args.Browser.GetZoomLevelAsync().Result != zoom) { chrome.SetZoomLevel(zoom); Thread.Sleep(50); }
                    }
                    catch { }
                    firstLoad++;
                }
                // These JS and CSS modifications built into EngageRC
                string hotfixJS = "";
                string hotfixCSS = "/* Fix for dropdowns */ ul.dropdown-menu[style=\\"opacity: 1;\\"] {display: block !important; } /* End fix for dropdowns */";
                // Inject custom javascript and css code on page load
                chrome.ExecuteScriptAsync(hotfixJS);
                chrome.ExecuteScriptAsync("var engageRCSS = document.getElementById('EngageRCSS'); if (!engageRCSS) { var node = document.createElement('style'); node.setAttribute('id', 'EngageRCSS'); node.innerHTML = \"" + hotfixCSS +"\"; document.body.appendChild(node); }");
                if (File.Exists(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, @"Resources\Custom.js"))) { chrome.ExecuteScriptAsync(System.IO.File.ReadAllText(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, @"Resources\Custom.js"))); }
                if (File.Exists(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, @"Resources\Custom.css"))) { chrome.ExecuteScriptAsync("var customCSS = document.getElementById('customcss'); if (!customCSS) { var node = document.createElement('style'); node.setAttribute('id', 'customcss'); node.innerHTML = \"" + System.IO.File.ReadAllText(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, @"Resources\Custom.css")).Replace("\n", String.Empty).Replace("\r", String.Empty).Replace("\t", String.Empty).Replace("\"", "\\"") + "\"; document.body.appendChild(node); }"); }
            }
         }

我在显示通知的时候也有。这很可能是我的问题,因为这是主应用程序线程中的 运行ning... (https://github.com/dylanlangston/EngageRC/blob/master/NotificationSupport.cs)

public void displayNotification(string Title = "EngageRC", string Message = "")
            {
                // Display notification for 5 seconds
                Notify notification = MainWindow.notification;
                try
                {
                    if (!IsActive(hWnd)) // Check if application is already active.
                    {
                        string config = ConfigReader.GetConfigValue("NotificationsDisabled").ToLower();
                        if (!(config == "true" || config == "1"))
                        {
                            notification.NewNotification(Title, Message, 5000);
                        }
                        config = ConfigReader.GetConfigValue("GetFocusOnCallDisabled").ToLower();
                        if (!(config == "true" || config == "1") && (Message == "You have incoming call"))
                        {
                            // Minimize window
                            ShowWindow(hWnd, 0x02);
                            // Restore window to previous state.
                            ShowWindow(hWnd, 0x09);
                        }
                        config = ConfigReader.GetConfigValue("GetFocusOnPendingDispositionDisabled").ToLower();
                        if (!(config == "true" || config == "1") && (Message == "You have a disposition pending"))
                        {
                            // Minimize window
                            ShowWindow(hWnd, 0x02);
                            // Restore window to previous state.
                            ShowWindow(hWnd, 0x09);
                        }
                    }
                }
                catch { notification.SetIconVisible(false); }
                finally
                {
                    Thread.Sleep(4999);
                    notification.SetIconVisible(false);
                }
            }

根据我所听到的,我应该在与主应用程序不同的线程上制作通知表单 运行 吗?还是我跑题了?


更新: 我能够将通知移到它自己的线程中。我正在关闭这个问题,并将让用户测试黑屏是否仍然存在。

再次感谢您的帮助!!

@amaitland 的评论有助于缩小此问题的范围。