使用SetParent窃取另一个进程的主窗口,但保持消息循环分离

时间:2011-03-04 07:21:13

标签: c# winforms multithreading winapi activex

背景:我和我的同事正在维护我们继承的百万行遗留应用程序。它的前端是用VB6编写的,当我们将几乎所有资源用于将其转换为C#时,我们正在寻找快速和简单的方法。对我们具体问题的肮脏解决方案。

应用程序以插件方式运行。最多可以在网格样式的布局中同时加载20个单独的ActiveX控件。问题是ActiveX控件在他们自己的UI线程上完成所有处理,并且由于很多阻止等待网络访问,UI变得非常浓。当我们的托管C#应用程序加载这些控件时,它变得没有响应,因为有多少控件正在咀嚼UI资源什么都不做。最重要的是,控件很脆弱,在最轻微的挑衅时会崩溃。当它们在主C#应用程序中托管时,会造成严重的不稳定。

到目前为止,我和我最好的合作伙伴是按照ActiveX控件启动一个进程。这个过程,我们称之为代理,是另一个winforms应用程序。它使用命名管道与托管进程进行通信。托管过程创建一个窗口,加载我们选择的ActiveX控件(通过一些反射和AxHost魔术),并通过命名管道告诉主进程它的窗口句柄是什么。主进程使用SetParent和SetWindowPos的组合将代理应用程序移动到自身中以模拟插件。通过命名管道发送大小更新。

这很有效,直到ActiveX应用程序执行某种冗长的过程,我们在主窗口工作时点击它。有一段时间,主窗口是响应式的,但最终它会在子窗口等待其UI线程时变得无响应。我们怎样才能将子窗口保留在自己的完整线程上,同时还能获得SetParent的好处?

(如果有任何不清楚的地方,请通知我。)

1 个答案:

答案 0 :(得分:5)

我以前做过这个。它变得混乱。

我们在自己的AppDomain中运行每个插件,它启动了自己的UI线程。当我们没有使用不同的UI线程时,我们遇到了很多非常讨厌的问题。

这确实意味着您在AppDomains上进行通信的所有痛苦,但它是可行的。主要的是你需要在每个AppDomain /插件中运行Application.Run。通过大量的关注与他们之间进行沟通 - 即使关闭也很棘手。

祝你好运:)