简体   繁体   English

异步控制台程序在使用 CefSharp 完成任务时挂起

[英]Asynchronous console program hangs on completion of task using CefSharp

In my quest to create the perfect string result = browser.Browse(url) method, I have created a simple class library to demonstrate CefSharp.为了创建完美的string result = browser.Browse(url)方法,我创建了一个简单的类库来演示 CefSharp。 The code for that is:代码是:

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

This is the test harness, in a separate console project that references the CefSharpHeadlessBrowser project:这是引用 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);
    }
}

This actually works;这确实有效; it gets the HTML page source properly and displays it in the console window, just as it should.它正确获取 HTML 页面源代码并将其显示在控制台窗口中,就像它应该的那样。 But here's the problem: the console program hangs after displaying the page source.但问题来了:控制台程序在显示页面源后挂起。 It should exit immediately.它应该立即退出。 Which must mean that I'm doing something wrong with the asynchronous operations and causing a deadlock.这一定意味着我在异步操作上做错了并导致了死锁。

What could be the issue?可能是什么问题?

CefSharp has a Shutdown command; CefSharp 有一个 Shutdown 命令; I was able to solve the problem by adding the following method to the CefSharpHeadlessBrowser class:我能够通过将以下方法添加到CefSharpHeadlessBrowser类来解决问题:

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

And then changing the Test Harness to:然后将测试线束更改为:

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

This undoubtedly frees up any remaining threads that are running.这无疑会释放任何剩余的正在运行的线程。

I'll probably make the class IDisposable and wrap the calling code in a using statement.我可能会创建IDisposable类并将调用代码包装在using语句中。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM