Асинхронная консольная программа зависает при завершении задачи с использованием CefSharp

В моем стремлении создать идеальный 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 ответ

CefSharp имеет команду выключения; Я смог решить эту проблему, добавив следующий метод в CefSharpHeadlessBrowser учебный класс:

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

А затем изменив Test Harness на:

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 заявление.

Другие вопросы по тегам