1

为了创建完美的string result = browser.Browse(url)方法,我创建了一个简单的类库来演示 CefSharp。代码是:

public class CefSharpHeadlessBrowser
{
    public CefSharpHeadlessBrowser()
    {
        Cef.Initialize(new CefSettings { CachePath = "cache" }, false, true);
    }

    public string Browse(string url)
    {
        Task<string> result;

        var browserSettings = new BrowserSettings { WindowlessFrameRate = 1 };

        using (var browser = new ChromiumWebBrowser(url, browserSettings))
        {
            browser.WaitForBrowserToInitialize();

            browser.LoadPageAsync();

            // Wait awhile for Javascript to finish executing.
            Thread.Sleep(2000);

            result = browser.GetSourceAsync();
            Thread.Sleep(100);
        }
        return result.Result;
    }
}

public static class CefExtensions
{
    public static void WaitForBrowserToInitialize(this ChromiumWebBrowser browser)
    {
        while (!browser.IsBrowserInitialized)
        {
            Task.Delay(100);
        }
    }

    public static Task LoadPageAsync(this IWebBrowser browser)
    {
        var tcs = new TaskCompletionSource<bool>();

        EventHandler<LoadingStateChangedEventArgs> handler = null;
        handler = (sender, args) =>
        {
            if (!args.IsLoading)
            {
                browser.LoadingStateChanged -= handler;
                tcs.TrySetResult(true);
            }
        };

        browser.LoadingStateChanged += handler;
        return tcs.Task;
    }
}

这是测试工具,在引用 CefSharpHeadlessBrowser 项目的单独控制台项目中:

class Program
{
    static void Main(string[] args)
    {
        const string searchUrl = "https://www.google.com";

        var browser = new CefSharpHeadlessBrowser();

        var result = browser.Browse(searchUrl);
        Console.Write(result);
    }
}

这确实有效;它正确地获取 HTML 页面源并将其显示在控制台窗口中,就像它应该的那样。但问题是:控制台程序在显示页面源后挂起。 它应该立即退出。这一定意味着我在异步操作上做错了什么并导致死锁。

可能是什么问题?

4

1 回答 1

1

CefSharp 有一个 Shutdown 命令;我能够通过在类中添加以下方法来解决问题CefSharpHeadlessBrowser

    public void Shutdown()
    {
        Cef.Shutdown();
    }

然后将测试工具更改为:

class Program
{
    static void Main(string[] args)
    {
        const string searchUrl = "https://www.google.com";

        var browser = new CefSharpHeadlessBrowser();

        var result = browser.Browse(searchUrl);
        Console.WriteLine(result);
        browser.Shutdown();  // Added 
    }
}

这无疑释放了所有剩余的正在运行的线程。

我可能会创建类IDisposable并将调用代码包装在一个using语句中。

于 2016-04-28T19:08:41.660 回答