我有一个奇怪的错误,我不能理解。我有一个在运行的单独线程中创建的图形,我试图在线程外部访问IBaseFilter sampleGrabber,这在控制台应用程序中可以工作,但我将代码移到了一个新项目中,在那里我试图将sampleGrabber强制转换为ISampleGrabber,运行时报告了一个空引用异常。如果我调试sampleGrabber,它确实有ISampleGrabber接口,但是我不能再强制转换它。在运行图形的线程中移动代码允许我对其进行强制转换,但这对我的应用程序来说并不理想。
如何通过将what is a sampleGrabber清晰地转换为ISampleGrabber fail来出现空引用异常?
发布于 2013-08-20 00:42:08
问题是,DirectShow筛选器是早期的COM类,它们在引用计数、接口、绰号、持久性的一部分中实现了COM的子集-基本上所有的好东西都会持续数年-但它们完全忽略了公寓。DirectShow本身是多线程的,典型的情况是有一个控制线程,另外还有工作线程流。DirectShow概念假设您可以轻松地在线程之间传递接口指针,并且不涉及任何封送处理。
然后出现了带有检查COM包装器的.NET,并且DirectShow.NET包装了接口指针,就好像它们是全功能的单元感知COM指针一样。与此同时,微软停止了对DirectShow的更新(例如,提供了免费的线程封送拆收器Sample Grabber ),最终你遇到了这个问题,因为在.NET上,你不能用接口指针做一件理应简单的事情。
在本机代码域中使用API绝对没有问题,因为您可以跳过封送处理,直接使用指针。
您在一个公寓上构建图形,然后从另一个公寓上的示例Grabber获得回调(否则,在您的场景中,您只需在工作线程上执行某些操作)。您不能使用原始接口指针,例如。成员变量中的那些,因为.NET运行时检查将命中单元不匹配,特别是试图封送另一个单元的接口指针。
如果是带有源代码的自定义筛选器,您可以添加一个自定义IMarshal实现,或者利用free threaded marshaler在本机代码端修复.NET问题,或者添加一个帮助器来跨单元传递指针。
在.NET代码域中,最好的方法是避免使用来自多个单元的指针。可能有很多选择,但我想到的最简单的一个就是
CLSID_FilterGraphNoThread版本的Filter Graph Manager也就是说,要么使用STA而不使用额外线程接触指针,要么不使用STA。
发布于 2013-08-19 23:32:24
在尝试了IGlobalInterface和思考了Roman的评论之后,我意识到设置处理samplegrabber的函数最好是在另一个线程中,这样就绕过了STA。
https://stackoverflow.com/questions/17282185
复制相似问题