我有一个与 AppDomain 和 Windows 消息有关的问题。
要在 Internet Explorer 中托管的网页,其中包含 .Net WinForms UserControl 派生控件 - HelloWorldCtl。此控件位于 C# 编写的程序集 - HelloWorldControl.dll 中。该控件使用来自另一个用 C++/CLR 编写的程序集的代码 - HelloWorldLibCPP.dll。
HelloWorldCtl 加载 HelloWorldLibCPP.dll 并调用将创建 Win32 本机窗口的代码并将该窗口放置在 HelloWorldCtl 的区域中。
导航到网页,HelloWorldCtl 加载,我可以看到它以及 HelloWorldCtl 区域中心的本机窗口。
C# 控件和本机窗口都有一些消息处理程序,并且消息都可以正常工作并到达 C# 控件的窗口和本机窗口;鼠标点击、重新绘制等等……但是,本机窗口的一些消息处理程序需要调用作为本机窗口父级的 C# 控件上的方法。这是使用 C# 控件实现的接口完成的,并且本机窗口通过将其存储在 GCHandle 中(来自 System::Runtime::InteropServices)来保存对它的引用。我为 GCHandle 使用了 gcroot<> 模板。
当本机窗口中的代码尝试使用 GCHandle 调用 C# 控件上的任何方法时,此时会发生故障。(c++ 代码使用 /clr 编译为托管代码。)
抛出的异常是:
“无法跨 AppDomain 传递 GCHandle”
我放了一些调试代码来在 C# 和本机窗口中显示 CurrentDomain 的 Id 和 FriendName,我发现这些 AppDomain 并不相同。
在原生窗口的创建过程中,CurrentDomain 与 C# 控件相同,但是当原生窗口接收消息并处理这些消息时,CurrentDomain 与 C# 控件不同。
这种状况可以改变吗?是否可以让两个本机窗口消息处理程序在与 C# 控件相同的 AppDomain 中运行?
也许还有其他建议?
谢谢,罗杰