我正在使用Chromium Embedded Framework 3(通过CEFGlue)通过插件在第三方进程中托管浏览器。 CEF会旋转各种外部进程(例如渲染器进程)并管理这些进程的生命周期。
当第三方进程干净地退出时,将调用CefRuntime.Shutdown
并且所有进程都干净地退出。当第三方进程退出严重时(例如崩溃)我仍然在运行CEF可执行文件,这(有时)会导致主机应用程序出现问题,这意味着它不会再次启动。
我想要一种方法来确保调用主机应用程序退出CefRuntime.Shutdown
的任何方式,并且用户不会最终运行虚假进程。
我一直指向工作对象的方向(参见here),但这似乎很难在真正的解决方案中提供,因为在某些版本的Windows上它需要管理权限。
我还可以将CEF设置为在单进程模式下运行,但是文档指定这仅仅是为了“调试”,所以我假设在生产代码中将其运送出于某种原因是不好的(参见{{3} })。
我还有其他选择吗?
继续评论之后,我尝试将主机进程的PID传递给客户端(我可以通过覆盖OnBeforeChildProcessLaunch
来完成此操作)。然后我用以下代码创建了一个简单的看门狗:
ThreadPool.QueueUserWorkItem(_ => {
var process = Process.GetProcessById(pid);
while (!process.WaitForExit(5000)) {
Console.WriteLine("Waiting for external process to die...");
}
Process.GetCurrentProcess().Kill();
});
我可以在调试器中验证此代码是否执行以及我传入的PID是否正确。但是,如果我终止主机进程,我发现该线程只是以我无法控制的方式死亡,并且while
循环之后的行永远不会被执行(即使我用{{1替换它'我从来没有看到从这个帖子打印过的任何消息。
答案 0 :(得分:0)
对于后人,@ IInspectable建议的解决方案有效,但为了使其工作,我必须切换外部进程的实现以使用非多线程消息循环。
settings.MultiThreadedMessageLoop = false;
CefRuntime.Initialize(mainArgs, settings, cefWebApp, IntPtr.Zero);
Application.Idle += (sender,e) => {
if (parentProcess.HasExited) Process.GetCurrentProcess().Kill();
CefRuntime.DoMessageLoopWork();
}
Application.Run();