无法使CefSharp加载同步

问题描述 投票:3回答:1

我有一个屏幕外的ChromiumWebBrowser,用于在页面上运行一些JS并获取结果。

Load方法是同步的,但是在引发FrameLoadEnd事件之前,我无法运行JS代码,这意味着或我的目的Load是一个以FrameLoadEnd事件结尾的异步方法。

为了使代码更清晰,我尝试创建一种扩展方法,该方法将允许我使用await等待页面加载,而不是注册事件。但是,当我将此方法与TaskCompletionSource一起使用时,应该不会加载页面加载后应该运行的javascript,但是当使用AutoResetEvent并在其上等待时,代码可以正常工作。

此代码无效:

public static Task LoadPageAsync(this IWebBrowser browser, string address)
{
    TaskCompletionSource<bool> tcs = new TaskCompletionSource<bool>();
    browser.FrameLoadEnd += (sender, args) =>
    {
        if (args.IsMainFrame)
        {
            tcs.TrySetResult(true);
        }
    };
    browser.Load(address);
    return tcs.Task;
}

这就是:

public static AutoResetEvent LoadPageAsync(this IWebBrowser browser, string address)
{
    AutoResetEvent are = new AutoResetEvent(false);
    browser.FrameLoadEnd += (sender, args) =>
    {
        if (args.IsMainFrame)
        {
            are.Set();
        }
    };
    browser.Load(address);
    return are;
}

这是呼叫代码:

await _browser.LoadPageAsync("Some web address");
LoadScripts();

DoJsThing();
GetJsData();

[他们做同样的事情,但我觉得返回任务时的功能要比返回AutoResetEvent时清楚得多。

为什么我不能使用TaskCompletionSource表示我完成了?我做错什么了吗?

c# async-await chromium-embedded cefsharp
1个回答
5
投票
public static Task LoadPageAsync(IWebBrowser browser, string address = null)
    {
        var tcs = new TaskCompletionSource<bool>(TaskCreationOptions.RunContinuationsAsynchronously);

        EventHandler<LoadingStateChangedEventArgs> handler = null;
        handler = (sender, args) =>
        {
            //Wait for while page to finish loading not just the first frame
            if (!args.IsLoading)
            {
                browser.LoadingStateChanged -= handler;
                //Important that the continuation runs async using TaskCreationOptions.RunContinuationsAsynchronously
                tcs.TrySetResult(true);
            }
        };

        browser.LoadingStateChanged += handler;

        if (!string.IsNullOrEmpty(address))
        {
            browser.Load(address);
        }
        return tcs.Task;
    }

注意,我使用LoadingStateChanged是因为它可以更好地指示整个页面何时完成加载。

© www.soinside.com 2019 - 2024. All rights reserved.