无法获取浏览器网页的 HTML 源,异步到同步问题

Bub*_*bba 0 c# asynchronous async-await cefsharp

Visual Studio 2017、Windows 10、.NET Framework 4.8、CefSharp WinForms 83.4.20、平台目标 x64

创建了新的非常简单的 CefSharp Windows 窗体应用程序。我无法获取网页的 html 源代码。我想我已经查看了 StackOverflow 上的每个 CefSharp 和异步同步问题 - 尝试了很多解决方案 - 我的头已经变得糊涂了。这是我看到的第一个问题 - 我也有同样的问题。

从 CefSharp Web 浏览器获取 HTML 源代码

'浏览器.ViewSource();' 确实会弹出一个记事本,其中包含网页的源代码。但是当我尝试使用源代码获取字符串时 - 任务似乎永远不会运行。运行以获取网页源的任务显示 ---> Status = WaitingForActivation ---> 并且永远不会返回源。

我尝试过异步到同步的转换 - 可能有十种不同的方式。没有工作。一个 StackOverflow 解决方案建议使用 Application.DoEvents() - 所以我什至尝试过。

希望有人有一些想法。这个浏览器似乎有很大的潜力 - 但我需要获取网页源 html。

using System;
using System.Threading.Tasks;
using System.Windows.Forms;
using CefSharp;
using CefSharp.WinForms;
using System.Diagnostics;
namespace Test1
{
    public partial class Form1 : Form
    {
        public ChromiumWebBrowser browser;
        public Form1()
        {
            InitializeComponent();
            InitBrowser();
        }
        private void Form1_Load(object sender, EventArgs e)
        {
        }
        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            browser.Dispose();
            Cef.Shutdown();
        }
        private void exitToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Application.Exit();
        }
        public void InitBrowser()
        {
            Cef.Initialize(new CefSettings());
            browser = new ChromiumWebBrowser("https://google.com/");
            this.Controls.Add(browser);
            browser.Dock = DockStyle.Fill;
            browser.FrameLoadEnd += OnWebBrowserFrameLoadEnded;
        }
        void OnWebBrowserFrameLoadEnded(object sender, FrameLoadEndEventArgs e)
        {
            ChromiumWebBrowser BrowserSender = (ChromiumWebBrowser)sender;
            if (this.InvokeRequired)
            {
                this.Invoke(new MethodInvoker(() => { WebBrowserFrameLoadEnded(BrowserSender, e); }));
            }
            else
            {
                WebBrowserFrameLoadEnded(BrowserSender, e);
            }
        }
        void WebBrowserFrameLoadEnded(ChromiumWebBrowser BrowserSender, FrameLoadEndEventArgs e)
        {
            string html1 = null;
            Task<String> taskString1;

            if (e.Frame.IsMain)
            {
                //browser.ViewSource();
                taskString1 = Task.Run(() => GetBrowserSource(browser));
                while (taskString1.Status != TaskStatus.RanToCompletion)
                {
                    Application.DoEvents();
                    System.Threading.Thread.Sleep(100);
                }
                html1 = taskString1.Result;
                Debug.WriteLine("");
            }
        }

        async Task<string> GetBrowserSource(ChromiumWebBrowser Browser)
        {
            return await Browser.GetMainFrame().GetSourceAsync();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我的应用程序配置

<?xml version="1.0" encoding="utf-8"?>
<configuration>
    <startup> 
        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.8"/>
    </startup>
</configuration>
Run Code Online (Sandbox Code Playgroud)

我的packages.config

<?xml version="1.0" encoding="utf-8"?>
<packages>
  <package id="cef.redist.x64" version="83.4.2" targetFramework="net452" />
  <package id="cef.redist.x86" version="83.4.2" targetFramework="net452" />
  <package id="CefSharp.Common" version="83.4.20" targetFramework="net452" />
  <package id="CefSharp.WinForms" version="83.4.20" targetFramework="net452" />
</packages>
Run Code Online (Sandbox Code Playgroud)

aep*_*pot 5

看上去陷入了僵局。这就是正确async/await 使用的问题。

private async void WebBrowserFrameLoadEnded(ChromiumWebBrowser BrowserSender, FrameLoadEndEventArgs e)
{
    if (e.Frame.IsMain)
    {
        string html1 = await GetBrowserSource(BrowserSender);
        Debug.WriteLine(html1);
    }
}
Run Code Online (Sandbox Code Playgroud)

但为什么不简单地这样做呢?

private async void OnWebBrowserFrameLoadEnded(object sender, FrameLoadEndEventArgs e)
{
    if (e.Frame.IsMain)
    {
        ChromiumWebBrowser browserSender = (ChromiumWebBrowser)sender;
        string html = await browserSender.GetMainFrame().GetSourceAsync();
        Debug.WriteLine(html);
    }
}
Run Code Online (Sandbox Code Playgroud)

请注意,Application.DoEvents() 使用起来并不安全