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

问题描述

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

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

Get HTML source code from CefSharp web browser

'browser.ViewSource();' 确实会弹出带有网页来源的记事本。但是,当我尝试获取带有源代码的字符串时,该任务似乎从未运行过。运行以获取网页源的任务显示--->状态= 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();
        }
    }
}

我的app.config

<?xml version="1.0" encoding="utf-8"?>
<configuration>
    <startup> 
        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.8"/>
    </startup>
</configuration>

我的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>

解决方法

看起来像一个僵局。那是一个正确的async/await usage问题。

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

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

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);
    }
}

请注意,Application.DoEvents() isn't safe to use