在多线程应用程序中使用带有媒体基础接口的 P/Invoke 发生 AccessViolationException

Posted

技术标签:

【中文标题】在多线程应用程序中使用带有媒体基础接口的 P/Invoke 发生 AccessViolationException【英文标题】:AccessViolationException occured using P/Invoke with Media Foundation Interface in Multithread application 【发布时间】:2015-06-01 08:42:53 【问题描述】:

我正在使用 C# 中的 P/Invoke 从 C++ DLL 调用本机函数,如下所示:

    C++ DLL:

        extern "C"
        
            // Function: Create Wmv video from sequences image. Codec: WMV3 (VC-1)
            __declspec(dllexport) bool __stdcall CreateWMV(...)
            
            ...
            
        
    

    C# 包装类。我创建了 C# 包装类函数来映射本机 C++ 代码:

        [DllImport("AVIEncoder.dll", EntryPoint = "CreateWMV", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall)]
        [return: MarshalAs(UnmanagedType.Bool)]
        public static extern bool createWmv(...);
    

我确信参数在 C# 中正确编组,因为当我直接在客户端 C# 代码中调用时它会成功运行。 仅当我将函数置于后台线程时才会出现此问题。

private void Test()

....
createWmv(...); // This call was processed without issue
Thread backgroundThread = new Thread(
    new ThreadStart(()=>
    
        createWmv(...); // This call causes AccessViolationException
    

函数 createWmv() 使用媒体基础接口生成 Wmv 视频。我尝试调试,发现当我在本机代码中注释掉函数 IMFSinkWriter::WriteSample() 时,程序运行时不会导致异常。

因此,我想知道微软在 SinkWriter 实现中是否有一些奇怪的东西。 有没有人以这种方式使用 Media Foundation 时遇到同样的问题?

【问题讨论】:

我认为我们应该查看您的 C++ 代码以了解更多详细信息。 (这似乎是一个复杂的线程问题,与窗口句柄或线程堆有关。) 尝试设置ApartmentState to STA @oleksii 谢谢,它现在似乎与 STA ApartmentState 一起运行。 【参考方案1】:

关注oleksii的评论,我设置如下:

backgroundThread.TrySetApartmentState(ApartmentState.STA); // Add this to fix createWMV() in multithreading
backgroundThread.Name = "CreateVideoThead";
backgroundThread.Start();  

现在,程序可以正常运行了。感谢 C# 线程中 ApartmentState 的概念。

【讨论】:

以上是关于在多线程应用程序中使用带有媒体基础接口的 P/Invoke 发生 AccessViolationException的主要内容,如果未能解决你的问题,请参考以下文章

在多线程 C++ 程序中使用 std::vector 时应用程序崩溃

可以在多线程 DLL 的接口函数中创建线程吗?

Boost asio程序在多线程上崩溃

多线程(基础3)

多线程(基础3)

Python - 在多线程中使用随机数