我有一个奇怪的错误,我无法绕过头脑。我在一个运行的单独线程中创建了一个图表,我正在尝试访问在控制台应用程序中工作的线程之外的IBaseFilter sampleGrabber
,但我将代码移动到一个新项目,我正在尝试转换sampleGrabber
到ISampleGrabber
运行时抱怨空引用异常。如果我调试sampleGrabber
它确实有接口ISampleGrabber
但是我不能再进行转换。在运行图形的线程中移动代码允许我进行转换,但它不适合我的应用程序。
如何通过强制转换sampleGrabber
到ISampleGrabber
失败来显示空引用异常?
答案 0 :(得分:3)
问题是DirectShow过滤器是早期的COM类,它们在引用计数,接口,标记,持久性的一部分中实现COM的子集 - 基本上所有好事都持续了多年 - 但是它们完全忽略了公寓。 DirectShow本身是多线程的,通常有一个控制线程,并且有工作流线程。 DirectShow概念假设您可以轻松地在线程之间传递接口指针,并且不会涉及,预期和需要编组。
然后.NET检查了COM包装器,而DirectShow.NET包装了接口指针,好像它们是功能完备的公寓感知COM指针一样。同时,Microsoft停止向DirectShow提供更新(例如,使用免费的线程封送程序提供Sample Grabber),最终在.NET上遇到问题时,您无法通过接口指针执行一个简单的操作。
在本机代码域中使用API仍然没有问题,因为您可以跳过编组并使用直接指针。
您在一个公寓上构建图表,然后您从另一个公寓的Sample Grabber接听回电(或者,在您的方案中,您只需在工作线程上执行某些操作)。您不能使用原始接口指针,尤其是那些在成员变量中,因为.NET运行时检查会遇到公寓不匹配,尤其是试图编组另一个公寓的接口指针。
如果它是带有源代码的自定义过滤器,您可以添加自定义IMarshal
实现或利用free threaded marshaler来修复本机代码端的.NET问题,或者添加帮助程序以通过跨公寓的指针。
在.NET代码域中,最好的方法是避免使用来自多个公寓的指针。可能有选择,但我认为最简单的选择是
CLSID_FilterGraphNoThread
版本的Filter Graph Manager 即,使用STA并且没有额外的线程接触指针,否则不使用STA。
答案 1 :(得分:0)
在使用IGlobalInterface并思考Roman的评论之后,我意识到设置处理samplegrabber的函数最好是在另一个线程中,从而绕过STA。