我有一个场景,我在cefsharp浏览器中调用JavaScript方法,然后该javascript方法调用postMessage将消息发送到其他域上的iframe,然后iframe在我的代码库中调用.Net方法以通知它是完成其工作。
我的问题是调用线程阻止了回叫。
这是C#结束语的示例:
// This class can be called by Javascript from cefSharp browser
public class BrowserListener
{
public BrowserListener()
{
}
public void SendBool(bool result)
{
// This line doesn't get hit until after the timeout period
Log.Logger.Debug("Bool received from iframe {result}", result);
Shared.Result = result;
Shared.Received = true;
}
}
public static class Shared
{
// Only done this way for demonstration purposes
public static bool Received {get; set;} = false;
public static bool Result {get; set;} = false;
}
public class winCefBrowser : Window, IRequestHandler, IDownloadHandler, ILifeSpanHandler, IJsDialogHandler, ILoadHandler, IDialogHandler, IRenderProcessMessageHandler
{
// snipped a lot of interface implementation
private ChromiumWebBrowser mActiveView;
public winCefBrowser(IKiraSession activeSession)
{
CefSettings settings = new CefSettings();
settings.RemoteDebuggingPort = 1212;
settings.IgnoreCertificateErrors = false;
if (!Cef.IsInitialized)
{
Cef.Initialize(settings, performDependencyCheck: true, browserProcessHandler: null);
}
var v = new ChromiumWebBrowser();
var s = new BrowserSettings();
s.ImageLoading = CefState.Disabled;
v.BrowserSettings = s;
v.RequestContext = new RequestContext();
mActiveView = v;
// We have a tab control with the browser tab on it
var loNewTab = new TabItem { Header = "New" };
tabBrowser.Items.Add(loNewTab);
mActiveView.DownloadHandler = this;
mActiveView.RequestHandler = this;
mActiveView.LifeSpanHandler = this;
mActiveView.JsDialogHandler = this;
mActiveView.LoadHandler = this;
mActiveView.DialogHandler = this;
var opt = new BindingOptions {CamelCaseJavascriptNames = false};
mActiveView.RegisterAsyncJsObject("ourNet", new BrowserListener(),opt);
loNewTab.Content = mActiveView;
}
public async Task<bool> DoStuff(string myString)
{
Shared.Received = false;
var jsResponse = await mActiveView.EvaluateScriptAsync("myMethod('" + myString "');");
if (jsResponse.Result != "OK") return false;
var t = new Stopwatch();
t.Start();
// THIS LOOP IS WHERE THE PROBLEM IS
// The code will loop around here for 10 seconds, then return false
// THEN the call is received from the javascript method.
while (!Shared.Received)
{
Thread.Sleep(100);
if (t.Elapsed.Seconds > 10)
{
// Shouldn't hit this line
Log.Logger.Debug("Timed out waiting for response from inner javascript call.");
return false;
}
}
// Never hits this line
return Shared.Result;
}
}
此代码位于html主页上
function myMethod(message) {
// Simplified, this posts to the first iframe on the page
var x = document.getElementsByTagName("iframe")[0].contentWindow;
if (x !== null && x !== undefined) {
x.postMessage(message, "*");
}
return "OK";
}
此代码位于iframe中,该iframe托管在其他域中:
if (window.addEventListener) {
window.addEventListener("message", myListen, true);
} else {
window.attachEvent("onmessage", myListen);
}
function myListen(event) {
if (event.data == null) return;
// These log messages appear almost immediately in the debug console at http://localhost:1212
console.log("myListen triggered with event data:");
console.log(event.data);
ourNet.SendBool(true);
// This final log message is hit straight away.
// But .Net doesn't start processing the call to SendBool for 10 seconds.
console.log("Call back to .net completed.");
}
我正在WPF中使用CefSharp进行测试。我们最终的目标是在离屏模式下运行,因此,如果这是WPF特定的事情,我就不会介意。