Windows Forms应用程序,例如Google Chrome,具有多个进程

有没有办法使用C#来构建容器应用程序,其中每个选项卡实际上都是自己的进程,就像使用Google Chrome一样?

您可以使用SetParent Win32调用来执行此操作,但它确实充满了问题。 我有足够的麻烦使用来自不同AppDomains的窗口很好地工作 – 整个额外的过程会有更多的困难。

基本上两个进程之间可能需要进行大量的沟通 – 例如resize会变得非常痛苦,以及如果儿童应用程序想要退出等情况会发生什么。这一切都是可行的,但在做之前我会仔细考虑。 对于浏览器来说它很有意义(免责声明:我为谷歌工作),但对于大多数其他应用程序来说,它真的不值得付出努力。

(你想要创建实际的.NET应用程序的“标签”吗?如果是这样,我说这变得非常容易 – 我可以给你一个很大的提示,即每个UI都应该在自己的AppDomain中运行自己的UI线程如果你不这样做,你会得到非常奇怪的效果!)

对于那些对多进程应用程序的实际实现感兴趣的人,我在我的网站上写了一篇关于它的文章: Google Chrome等多进程C#应用程序

我已经包含了C#代码。 它已经过测试,可以与.NET 2.0,.NET 3.0和.NET 3.5一起使用。

命名管道:进程如何与彼此通信

由于您的问题专门询问了Google Chrome,因此您应该知道Chrome使用命名管道在流程之间进行通信。

在我上面提到的C#源代码中有2个文件:PipeServer.cs和PipeClient.cs。 这两个文件是Named Pipes Windows API的瘦包装器。 它经过了充分的测试,因为成千上万的人使用我们的产品。 因此稳定性和稳健性是必需的。

我们如何使用多流程设计

现在您已经完成了拼图的所有部分,让我告诉您我们如何在我们的应用程序中使用多进程设计。

我们的产品是一个完整的更新解决方案。 也就是说,有一个程序可以构建更新补丁 (与讨论无关),一个独立的更新程序( wyUpdate – 也是开源 ),以及我们的用户在其C#或VB.NET表单上放置的自动更新程序控件 。

我们使用命名管道在独立更新程序(wyUpdate)和程序表单上的自动更新程序控件之间进行通信。 wyUpdate向自动更新程序报告进度,自动更新程序可以告诉wyUpdate取消进度,开始下载,开始提取等。

事实上,我们使用的确切命名管道代码包含在我上面提到的文章中: 像Google Chrome这样的多进程C#应用程序

为什么不应该使用多进程设计

正如Jon Skeet上面提到的,您应该对多进程模型有特定需求。 在我们的例子中,我们希望将更新程序与程序完全分开。 这样,如果更新程序以某种方式崩溃,您的程序将保持毫发无损。 我们也不想在2个地方复制我们的代码。

话虽如此,即使使用我们经过良好测试的命名管道封装器,进程间通信也很困难。 所以谨慎行事。

查看Chromium博客上的这篇文章 。 只有一个进程负责实际渲染到屏幕。

我的产品WindowTabs.com就是这样做的。 你需要使用Win32 – 我建议你避免使用SetParent,因为你最终附加了线程输入。 相反,在窗口上方绘制选项卡并使用SetWindowPos将窗口作为一组移动。 此外,如果您在Win32级别为表单提供父级,则某些第三方控件(如Infragistic)无法正常运行。

.NET 3.5中引入的System.AddIn API允许您在单独的AppDomain中使用UI控件。 通过一些跳跃,你也可以在不同的过程中使它工作。

这在WPF中以导航方式支持。 请参阅MSDN示例加载项返回UI 。

使用Windows Forms,使用System.AddIn API看起来本身不太可能。 请参阅System.AddIn架构师Jack Gudenkauf的这篇文章。

但是,WinForms有一个解决方法。 您可以通过一些小工具来完成这项工作:请参阅BCL团队的博客System.AddIn主机和加载项中的Windows窗体支持

是。 您可以使用System.Diagnostics.Process生成新进程。 例如,使用某种forms的进程间通信 (IPC) ,.NET Remoting ,您可以在进程之间进行通信。 然后,您可以将新进程的窗口/表单的父级设置为第一个进程的窗口(选项卡),以便它显示在那里。

在不深入了解可扩展性堆栈的情况下,您可以使用System.Addin命名空间来构建一个应用程序,该应用程序本身可以创建插件作为可视化的单个选项卡,并将每个选项卡/插件设置为out进程,这是一种开箱即用的行为。

它将具有与chrome选项卡相同的function。