Using SetParent to steal the main window of another process but keeping the message loops separate

孤者浪人 提交于 2019-12-21 20:47:42

问题


Background: My coworker and I are maintaining a million-line legacy application we inherited. Its frontend is written in VB6, and as we're devoting almost all of our resources to converting it to C#, we are looking for quick & dirty solutions to our specific problem.

The application behaves in a plugin-ish manner. There are up to 20ish separate ActiveX controls that can be loaded at once in a grid-style layout. The problem is that the ActiveX controls do all of their processing on their own UI thread, and as a lot of it is blocking waiting on network access, the UI gets very soupy. When our hosting C# app loads these controls, it becomes unresponsive because of how many controls are chewing up UI resources doing nothing. To top it off, the controls are fragile and will crash at the slightest provocation. When they are hosted in the main C# app, it creates serious instability.

The best my coworker and I have come up with so far is starting a process per ActiveX control. This process, which we call the proxy, is another winforms app. It uses named pipes to communicate with the hosting process. The hosting process creates a window, loads an ActiveX control of our choice (via some reflections & AxHost magic), and tells the main process what its window handle is via the named pipe. The main process uses a combination of SetParent, and SetWindowPos to move the proxy application into itself to emulate a plugin. Size updates are sent via the named pipe.

This works well enough until the ActiveX application does some sort of lengthy process and we click around on the main window while it's working. For awhile the main window is responsive, but eventually it becomes unresponsive as the child window waits for its UI thread. How can we keep the child windows on their own complete thread while still getting the benefits of SetParent?

(please let me know if anything isn't clear!)


回答1:


I've done this before. It gets messy.

We were running every plugin in its own AppDomain, which started up its own UI thread. We did this after running into lots of really nasty issues when we didn't use different UI threads.

It does mean that you have all the pain of communicating across AppDomains, but it's feasible. The main thing is that you'll need to run Application.Run in each AppDomain/plugin. Communicate between them with a huge amount of care - even shutting down is tricky.

Good luck :)



来源:https://stackoverflow.com/questions/5190881/using-setparent-to-steal-the-main-window-of-another-process-but-keeping-the-mess

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!