当从外部线程调用时,.net 单元测试崩溃并显示“无法通过 AppDomains 传递 GCHandle”
Posted
技术标签:
【中文标题】当从外部线程调用时,.net 单元测试崩溃并显示“无法通过 AppDomains 传递 GCHandle”【英文标题】:.net unit test crashes with "Cannot pass a GCHandle across AppDomains" when called from foreign thread 【发布时间】:2010-02-15 15:51:10 【问题描述】:我正在编写一个 C# 单元测试来测试涉及线程的 C++/CLI 功能。
C++/CLI 代码实现了 DirectShow 过滤器,即用于渲染电影的 Windows API。因此,我创建了 DirectShow 对象,告诉它通过我的 C++/CLI 过滤器运行 AVI,等待渲染完成,然后退出。我的过滤器有一个回调,将视频帧提供给 C# 进行处理。 DirectShow 的工作原理是它创建自己的线程并从该线程调用我的 COM 对象。
现在,当我正常运行我的代码时,这些东西可以工作,但是当从 Resharper 运行单元测试时,它会失败并出现错误“无法通过 AppDomains 传递 GCHandle”。
似乎出了问题的是 Resharper 在其测试运行程序中使用了 AppDomains,而 DirectShow 线程不知何故与此 appdomain 无关。
那么,如何让 Resharper 进行这项测试?是否有 NUnit/Resharper 设置来控制是否使用 appdomains?我可以以某种方式告诉 CLR 线程与特定的应用程序域相关联吗?你知道其他实用的解决方法吗?
TIA 一月
【问题讨论】:
【参考方案1】:我设法让它按照http://www.lenholgate.com/archives/000856.html中描述的程序工作
这描述了如何使非托管函数指针指向托管类中的方法。当您调用此函数指针时,您将进入最初创建对象的托管应用程序域。这修复了我的 appdomain 错误。
【讨论】:
感谢您提供此链接。我一直在努力让我的事件系统在一个单独的本机线程调用托管世界的情况下工作。我使用持有gcroot<Action^>
的类构建了一个简单的机制,以防止对我的委托+ 由Marshal.GetFunctionPointerForDelegate()
创建的指向我的委托的函数指针进行垃圾收集。在我的事件触发器中,我只需调用函数指针,AppDomain 转换就会自动完成。【参考方案2】:
您没有提及您正在使用的 ReSharper 版本。尝试使用最新的ReSharper 5.0 Nightly Build 运行测试。那里的人重写了测试运行程序以天真地支持 Nunit。如果这不起作用,我建议您在他们的新Bug Tracking system 上将此问题报告为问题。
【讨论】:
感谢您的打扰。与此同时,我设法解决了根本原因,但我肯定会尽快用 5.0 进行测试。以上是关于当从外部线程调用时,.net 单元测试崩溃并显示“无法通过 AppDomains 传递 GCHandle”的主要内容,如果未能解决你的问题,请参考以下文章
单元测试项目在实例 IPublicClientApplication 的 AcquireTokenInteractive 方法上崩溃