CefSharp调用IJavascriptCallback导致应用程序卡死问题求助
可能的原因及解决方法
- 同步上下文死锁
你当前的await callback.ExecuteAsync(parms)默认会捕获当前线程的同步上下文(如果是UI线程调用就会捕获UI同步上下文),而CEF内部执行JS回调需要占用UI线程资源,就会形成互相等待的死锁,导致程序冻结。
解决方法:在await后添加.ConfigureAwait(false),不捕获原有同步上下文,代码如下:
JavascriptResponse response = await callback.ExecuteAsync(parms).ConfigureAwait(false);
- 绑定对象异步配置错误
你注册绑定对象时设置了isAsync: false,该配置下所有JS调用C#绑定方法的逻辑都会在CEF渲染主线程同步执行,如果你的ExecuteCallback是在绑定方法内部调用,就会出现CEF线程等待JS回调执行、JS回调执行又等待CEF线程空闲的死锁。
解决方法:修改注册逻辑的isAsync参数为true:
Browser.JavascriptObjectRepository.Register("worker", Browser.JsWorker, isAsync: true);
- 无超时逻辑导致无限等待
如果JS侧的回调函数存在同步阻塞逻辑(比如死循环、长时间同步计算、循环调用C#绑定方法),ExecuteAsync会一直等待JS返回,导致程序卡住。
解决方法:给执行逻辑添加超时处理,修改后的方法如下:
[JavascriptIgnore] private async Task<bool> ExecuteCallback(IJavascriptCallback callback, params object[] parms) { if (callback != null && callback.CanExecute && !callback.IsDisposed) { var executeTask = callback.ExecuteAsync(parms); // 超时时间可根据业务调整,此处设置为5秒 if (await Task.WhenAny(executeTask, Task.Delay(5000)) == executeTask) { JavascriptResponse response = executeTask.Result; return response.Success && bool.TryParse(response.Result?.ToString(), out bool result) && result; } return false; } return false; }
- 遗留绑定模式兼容性问题
你开启了LegacyBindingEnabled使用旧版绑定模式,该模式在较新版本的CefSharp中存在较多线程同步的已知问题,线程安全处理较差。
解决方法:如果使用的是V79及以上版本的CefSharp,建议关闭LegacyBindingEnabled,改用官方推荐的新版异步绑定方案。
内容的提问来源于stack exchange,提问作者Мурадин Боташев
相关产品推荐
相关产品推荐

