4

我有一个奇怪的错误,我无法理解。我有一个在运行的单独线程中创建的图表,我试图访问IBaseFilter sampleGrabber在控制台应用程序中工作的线程外部,但我将代码移动到一个新项目,并且我试图将其投射sampleGrabberISampleGrabber运行时抱怨空引用异常。如果我调试sampleGrabber它确实有接口ISampleGrabber但是我不能再转换它了。在运行图表的线程中移动代码可以让我强制转换它,但它不适合我的应用程序。

空引用异常如何通过强制转换明显失败的内容sampleGrabberISampleGrabber出现?

4

2 回答 2

3

问题是 DirectShow 过滤器是早期的 COM 类,它们在引用计数、接口、名字对象、持久性方面实现了 COM 的一个子集——基本上所有的好东西都会持续多年——但是它们完全忽略了公寓。DirectShow 本身是多线程的,通常有一个控制线程,旁边还有工作流线程。DirectShow 概念假定您可以轻松地在线程之间传递接口指针,并且不涉及、预期和要求的封送处理。

然后是带有检查 COM 包装器的 .NET,并且 DirectShow.NET 包装了接口指针,就好像它们是功能齐全的单元感知 COM 指针一样。与此同时,Microsoft 停止了对 DirectShow 的更新(例如,为 Sample Grabber 提供免费的线程封送处理程序),最终您在 .NET 上遇到了这个问题,您无法使用接口指针执行所谓的简单操作。

在本机代码域中使用 API 仍然绝对没有问题,因为您可以跳过那里的编组并使用直接指针。

您在一个公寓上构建图表,然后在另一间公寓上收到来自 Sample Grabber 的回调(或者,在您的场景中,您只需在工作线程上执行某些操作)。您不能使用原始接口指针,尤其是。成员变量中的那些,因为 .NET 运行时检查会遇到单元不匹配,尤其是试图为另一个单元编组接口指针。

如果它是带有源代码的自定义过滤器,您可以添加自定义IMarshal实现或利用免费线程封送处理程序来修复本机代码端的 .NET 问题,或者添加帮助程序以跨单元传递指针。

在 .NET 代码域中,最好的方法是避免使用来自多个公寓的指针。可能有选择,但我想到的最简单的一个是

  • 在 MTA 中工作以便能够让多个线程访问 DirectShow 接口指针
  • 使用CLSID_FilterGraphNoThreadFilter Graph Manager 的版本
  • 在专用线程上初始化和终止过滤器图,该线程在图操作期间调度窗口消息

也就是说,要么使用 STA,并且没有额外的线程接触指针,要么不使用 STA。

于 2013-08-19T16:42:07.920 回答
0

在玩弄了IGlobalInterface并思考了Roman的评论后,我意识到设置处理samplegrabber的函数最好在另一个线程中,从而绕过STA。

于 2013-08-19T15:32:24.480 回答