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

时间:2016-04-28 18:42:58

标签: c# cefsharp cefsharp.offscreen

在我创建完美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页面源并将其显示在控制台窗口中,就像它应该的那样。但问题出现了:控制台程序在显示页面源后挂起。它应该立即退出。这必然意味着我对异步操作做错了并导致死锁。

可能是什么问题?

1 个答案:

答案 0 :(得分: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语句中。