c# - 使用 SetParent 窃取另一个进程的主窗口但保持消息循环独立

标签 c# winforms multithreading winapi activex

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

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

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

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

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

最佳答案

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

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

这确实意味着您会遇到跨 AppDomain 通信的所有痛苦,但这是可行的。最主要的是您需要在每个 AppDomain/插件中运行 Application.Run。非常小心地在它们之间进行通信 - 甚至关闭也很棘手。

祝你好运:)

关于c# - 使用 SetParent 窃取另一个进程的主窗口但保持消息循环独立,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5190881/

相关文章:

multithreading - Silverlight-延误行动之火-

c# - 如何附加包含 n 到 n 关系的对象?

c# - 要在服务器上上传任何内容...使用什么?

c# - 在windows窗体中显示透明gif文件

c# - WinForms:为什么在显示文件夹浏览器对话框时出现 InvalidCastException?

c# - 正在运行的BackgroundWorker的处理

c# - C# .net 核心中的 Path.GetDirectoryName

c# - Azure队列存储 Visual Studio 本地主机从QueueClient发送到毒队列的所有队列消息

c# - 这是状态消息显示的最佳方式吗?

python - csv.DictReader 只读取某些行