在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;
}
答案 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
。