Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/262.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/loops/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 使用SetParent窃取另一个进程的主窗口,但保持消息循环分开_C#_Winforms_Multithreading_Winapi_Activex - Fatal编程技术网

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

C# 使用SetParent窃取另一个进程的主窗口,但保持消息循环分开,c#,winforms,multithreading,winapi,activex,C#,Winforms,Multithreading,Winapi,Activex,背景:我的同事和我正在维护一个我们继承的百万行遗留应用程序。它的前端是用VB6编写的,当我们投入几乎所有的资源将其转换为C#时,我们正在寻找针对特定问题的快速而肮脏的解决方案 应用程序以插件式的方式运行。在网格样式的布局中,最多可以同时加载20个独立的ActiveX控件。问题是ActiveX控件在其自己的UI线程上执行所有处理,并且由于很多控件在等待网络访问时阻塞,UI变得非常糟糕。当我们的托管C#应用程序加载这些控件时,它会变得无响应,因为有多少控件在无所事事地占用UI资源。最重要的是,控制装

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

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

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

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


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

我以前做过。事情变得一团糟

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

这确实意味着您要承受跨应用程序域通信的所有痛苦,但这是可行的。最重要的是,您需要在每个AppDomain/插件中运行
应用程序。他们之间的沟通要非常小心,即使是关机也很棘手


祝您好运:)

作为代理(子)应用程序的一部分,我们使用了Application.run(new Form1())[或多或少]。启动的窗口是完全独立的可执行文件,显示在任务管理器和所有内容中。当我们设置父线程时,它们仍然锁定我们的UI线程:(@insta:Hmm。那听起来很奇怪。如果你闯入调试器,它会阻塞什么?@insta:这是意料之中的,当你调用时(跨线程边界调用SetParent时),因为。哦,@insta:So简言之:虽然你的UI可以很好地跨线程分布(无论如何都不会工作),将这些主机进程重新设置为同一父进程的父进程会附加它们的所有输入队列。当一个ActiveX控件处理输入时,其他控件(或父控件)都不会can.Input是严格序列化的。这听起来真的是一个摆脱束缚的好时机,只需将其实现为一个本机Win32托管应用程序,您就可以很好地控制所有这些问题,@ChrisBecke:“您可以很好地控制所有这些问题”-不,您没有。这些规则是一成不变的,您无法更改它们。(您可以向Microsoft提交设计更改请求,并要求他们为您重写窗口子系统。)跨线程调用
SetParent
,附加这些线程的输入队列。这与编程语言或运行时环境无关。