EvaluateScriptAsync挂起
EvaluateScriptAsync hanging
在 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;
}
虽然您在 BackgroundWorker
线程中分配 FrameLoadEnd
,但它实际上是在底层 CEF UI
线程上执行的,因此您无法在没有问题的情况下阻止它。
我通常建议您从事件处理程序中生成一个 Task
来完成您的工作。
正如 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;
}
作为一般规则,在异步代码上使用 Task.Wait
是个坏主意;相反,你应该 use async "all the way down". See also Don't Block on Async Code by Stephen Cleary。简短的回答是,如果您在具有同步上下文的应用程序中执行此操作,您可能会导致循环等待同步上下文(并因此导致死锁)。我链接到的文章有几个这样的例子,但我强烈建议如果可能的话在这里用await
替换Task.Wait
。
在 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;
}
虽然您在 BackgroundWorker
线程中分配 FrameLoadEnd
,但它实际上是在底层 CEF UI
线程上执行的,因此您无法在没有问题的情况下阻止它。
我通常建议您从事件处理程序中生成一个 Task
来完成您的工作。
正如 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;
}
作为一般规则,在异步代码上使用 Task.Wait
是个坏主意;相反,你应该 use async "all the way down". See also Don't Block on Async Code by Stephen Cleary。简短的回答是,如果您在具有同步上下文的应用程序中执行此操作,您可能会导致循环等待同步上下文(并因此导致死锁)。我链接到的文章有几个这样的例子,但我强烈建议如果可能的话在这里用await
替换Task.Wait
。