EvaluateScriptAsync挂起

时间:2015-10-17 11:40:11

标签: c# asynchronous cefsharp

在CefSharp WinForms中,我试图在页面加载后使用JS获取页面的html源代码,但是应用程序正在冻结。我正在使用BackgroundWorker,相关功能如下:

void bw_DoWork(object sender, DoWorkEventArgs e)
{
    browser.Load("http://www.google.com");

    browser.FrameLoadEnd += delegate
    {
        object js = EvaluateScript(browser, "1+1");
        MessageBox.Show(js.ToString());
    };
}

object EvaluateScript(ChromiumWebBrowser b, string script)
{
    var task = b.EvaluateScriptAsync(script);
    task.Wait();
    return task.Result;
}

3 个答案:

答案 0 :(得分:6)

正如amaitland指出的那样,FrameLoadEnd通过在UI线程中运行导致挂起。以下代码正在运行:

void bw_DoWork(object sender, DoWorkEventArgs e)
{
    first.Load("http://www.google.com");

    browser.FrameLoadEnd += delegate
    {
        Task task = new Task(() => {
            object js = EvaluateScript(browser, "document.getElementsByTagName('html')[0].innerHTML;");
            MessageBox.Show(js.ToString());
        });
        task.Start();
    };
}

static object EvaluateScript(ChromiumWebBrowser b, string script)
{
    var task = b.EvaluateScriptAsync(script);
    task.Wait();
    JavascriptResponse response = task.Result;
    return response.Success ? (response.Result ?? "") : response.Message;
}

答案 1 :(得分:3)

虽然您在FrameLoadEnd线程中分配BackgroundWorker,但它实际上是在基础CEF UI线程上执行的,您无法在没有问题的情况下阻止它。

我通常建议您在事件处理程序中生成Task以完成您的工作。

答案 2 :(得分:2)

作为一般规则,在异步代码上使用Task.Wait是一个坏主意;相反,你应该use async "all the way down"。另见Stephen Cleary的Don't Block on Async Code。简短的回答是,如果在具有同步上下文的应用程序中执行此操作,则可能导致循环等待同步上下文(从而导致死锁)。我链接的文章有几个例子,但是如果可能的话,我强烈建议用Task.Wait替换await