C# Can';不要使负载同步

C# Can';不要使负载同步,c#,async-await,chromium-embedded,cefsharp,C#,Async Await,Chromium Embedded,Cefsharp,我有一个屏幕外的ChromiumWebBrowser,我用它在页面上运行一些JS并返回结果 Load方法是同步的,但在引发FrameLoadEnd事件之前,我无法运行JS代码,这意味着Load是以FrameLoadEnd事件结束的异步方法 为了让代码更清晰,我尝试创建一个扩展方法,允许我使用wait等待页面加载,而不是注册到事件。但是当我在TaskCompletionSource中使用此方法时,页面加载后应该运行的javascript没有加载,但是当使用AutoResetEvent并等待它时,代

我有一个屏幕外的ChromiumWebBrowser,我用它在页面上运行一些JS并返回结果

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

为了让代码更清晰,我尝试创建一个扩展方法,允许我使用
wait
等待页面加载,而不是注册到事件。但是当我在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;
}
这是调用代码:

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

DoJsThing();
GetJsData();
它们做同样的事情,但我觉得返回任务时函数的意图比返回AutoResetEvent时要清楚得多

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

公共静态任务LoadPageAsync(IWebBrowser浏览器,字符串地址=null)
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;
}
{ var tcs=新TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); EventHandler=null; 处理程序=(发送方,参数)=> { //等待while page完成加载,而不仅仅是第一帧 如果(!args.IsLoading) { browser.LoadingStateChanged-=处理程序; //重要信息:继续使用TaskCreationOptions异步运行。RunContinuationsAsynchronously tcs.TrySetResult(真); } }; browser.LoadingStateChanged+=处理程序; 如果(!string.IsNullOrEmpty(地址)) { 浏览器加载(地址); } 返回tcs.Task; }

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

Wait
在页面加载上,而不是在后面的
LoadScripts()
中的javascript加载上,对吗?Wait,是
load
同步方法吗?加载是同步的,但是在主框架加载之前,不会做任何有意义的事情(或者至少是我关心的事情)。这意味着在常规代码中,我会调用Load,然后我的程序的其余部分将在FrameLoadEnd的事件代码中继续,这会导致代码中出现奇数跳转。事件应该在页面加载后立即发生?该事件是在页面加载后由库引发的,是的。谢谢,这很有效。我尝试分叉最小的示例,但无法重现问题。@amaitland我在中没有看到NavStateChanged事件属性,在哪里可以找到它?使用CefSharp 47.0.2。它被重命名为
LoadingStateChanged
,请参阅示例此示例适用于屏幕外解决方案。在显示窗体之前尝试在WinForms应用程序中完全加载页面会使程序员的生活陷入噩梦。链接已被替换为代码示例,该示例摘自
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;
}