【问题标题】:Working with CLSID_FilterGraph across different threads跨不同线程使用 CLSID_FilterGraph
【发布时间】:2013-08-09 16:33:40
【问题描述】:

我在我的 Qt 应用程序中使用 DirectShow。

为了创建 Filter Graph 的实例,我使用 QtConcurrent::run(即使用全局应用程序线程池中的可用线程之一)。

这是一个在 QThreadPool 中运行的简化代码示例:

graph_ptr createMovieGraph(const QString & file)
{
     ::CoInitializeEx(nullptr, COINIT_MULTITHREADED);
     auto * dst = graph_ptr(new MovieGraph(path));
     ::CoUninitialize();

     return dst;
}

稍后,我在 UI 线程中删除了我的 graph_ptr 对象。 AFAIK,QApplication UI 线程在 STA 线程模型中工作,但删除工作没有任何崩溃或内存泄漏。对吗?

有时我需要在 UI 线程中暂停或恢复我的 graph_ptr 对象。

// UI Thread
_graph_ptr->pause();

这是 graph_ptr 对象中的“暂停”实现:

_mediaControlInterface->Pause();
// ...
// CComPtr<IMediaControl>   _mediaControlInterface;

在graph_ptr对象初始化时在QThreadPool中查询了IMediaControl接口。

事实证明,我使用 UI 线程 (STA) 中的对象,而该对象是在 QThreadPool (MTA) 线程中创建的。 一切正常而不会崩溃,但我想我不能在具有不同线程模型的线程之间使用对象?

提前致谢。

【问题讨论】:

    标签: qt com directshow


    【解决方案1】:
     ::CoInitializeEx(nullptr, COINIT_MULTITHREADED);
     auto * dst = graph_ptr(new MovieGraph(path));
     ::CoUninitialize();
    

    这看起来不太好。 CoUninitialize 必须在所有 COM 活动完成后调用。要添加到这一点,您必须检查返回的状态代码。在 STA 线程上,这将导致 CoInitializeEx 出现错误,然后导致 CoUninitialize 不匹配。

    这很可能会导致访问冲突。也许你只是没有接触到他们。 DirectShow 使用简化的 COM,您可以在公寓之间传递原始指针,但是您必须正确完成最重要的事情:初始化/取消初始化、引用计数。为了避免麻烦,您需要在 STA 线程上创建、运行、停止和释放图表。

    【讨论】:

    • 罗曼,感谢您的解释。我还有一个问题:“::CoUninitialize()”是否会破坏我的应用程序中的 MTA(因为我已经引用了在 MTA 中创建的对象)?
    • CoUninitialize 字面意思是:“在这个线程上,我已经完成了 COM”。进一步做COM可能会有麻烦。 MTA 可能跨越多个线程,因此此调用不一定会完全“销毁”MTA。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-07
    • 1970-01-01
    • 1970-01-01
    • 2014-11-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多