【问题标题】:Using SetParent to steal the main window of another process but keeping the message loops separate使用 SetParent 窃取另一个进程的主窗口,但保持消息循环分开
【发布时间】:2011-03-04 07:21:12
【问题描述】:

背景:我和我的同事正在维护我们继承的一个百万行的遗留应用程序。它的前端是用 VB6 编写的,由于我们将几乎所有的资源都用于将其转换为 C#,因此我们正在为我们的特定问题寻找快速而肮脏的解决方案。

应用程序以插件方式运行。有多达 20 个独立的 ActiveX 控件可以在网格样式布局中一次加载。问题是 ActiveX 控件在它们自己的 UI 线程上进行所有处理,并且由于其中很多都阻塞了等待网络访问,因此 UI 变得非常糟糕。当我们的托管 C# 应用程序加载这些控件时,它会变得无响应,因为有多少控件正在吞噬 UI 资源而无所事事。最重要的是,控件很脆弱,只要稍有挑衅就会崩溃。当它们托管在主 C# 应用程序中时,会造成严重的不稳定。

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

在 ActiveX 应用程序执行某种冗长的过程并且我们在其工作时单击主窗口之前,这已经足够好用了。主窗口有一段时间是响应式的,但最终由于子窗口等待其 UI 线程而变得无响应。我们如何才能让子窗口保持在自己的完整线程上,同时仍然获得 SetParent 的好处?

(如果有什么不清楚的地方请告诉我!)

【问题讨论】:

  • 这听起来确实是摆脱高抬腿的好时机,只需将其实现为原生 Win32 托管应用程序,您就可以很好地控制所有这些问题,
  • @ChrisBecke:“你可以很好地控制所有这些问题” - 不,你没有。这些规则是一成不变的,你无法改变它们。 (好吧,您可以向 Microsoft 提交设计更改请求,并要求他们为您重写窗口子系统。)您跨线程调用 SetParent,附加这些线程的输入队列。这与编程语言或运行时环境无关。

标签: c# winforms multithreading winapi activex


【解决方案1】:

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

我们在它自己的 AppDomain 中运行每个插件,它启动了它自己的 UI 线程。当我们没有使用不同的 UI 线程时,我们遇到了很多真正令人讨厌的问题后才这样做。

这确实意味着您要承受跨 AppDomain 进行通信的所有痛苦,但这是可行的。主要的是你需要在每个 AppDomain/plugin 中运行Application.Run。非常小心地在它们之间进行沟通——即使关闭也很棘手。

祝你好运:)

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-22
  • 2022-10-14
  • 2012-05-26
  • 2013-05-10
  • 1970-01-01
相关资源
最近更新 更多