C# DirectShow/WPF线程问题

C# DirectShow/WPF线程问题,c#,wpf,directshow,C#,Wpf,Directshow,我正在使用WPF和DirectShow编写一个应用程序,遇到了一个棘手的问题。我的应用程序在使用DirectShowNet(DS的C#包装类)编写的静态类中通过静态方法Start()和Stop()使用DS。我的WPF窗口中有一个Windows窗体面板(通过WindowsFormsHost对象),我需要将图形渲染到该面板。下面是应用程序的一般流程:Start()方法构建图形并启动它;我传递windows窗体面板的句柄,并使用IVideoWindow界面对其进行渲染。Start()返回,图形在后台运

我正在使用WPF和DirectShow编写一个应用程序,遇到了一个棘手的问题。我的应用程序在使用DirectShowNet(DS的C#包装类)编写的静态类中通过静态方法Start()和Stop()使用DS。我的WPF窗口中有一个Windows窗体面板(通过WindowsFormsHost对象),我需要将图形渲染到该面板。下面是应用程序的一般流程:Start()方法构建图形并启动它;我传递windows窗体面板的句柄,并使用IVideoWindow界面对其进行渲染。Start()返回,图形在后台运行。在某一点上,会调用Stop();此方法停止图形并销毁它

只要我从同一个线程调用Start()和Stop(),一切都正常。但是,我需要在我的应用程序中从不同的线程调用它们。在这种情况下,我在破坏图形的代码部分得到一个异常(特别是当我试图枚举过滤器时)。我发现在使用DirectShow时需要使用多线程单元。使用Windows窗体应用程序很容易做到这一点;我只是在我的主方法上抛出一个[MTAThread],一切都正常

对于我的WPF应用程序,这显然不是一个选项。我的解决方法是在需要调用Start()和Stop()时启动新的MTA线程。这消除了异常,但引入了另一个问题。当Start()方法返回时,视频将从“渲染”面板中消失。如果我在Start()方法的末尾加上一个Sleep,视频将一直可见,直到睡眠结束。此外,我还验证了在视频消失后,图形会继续运行。有人对如何进行有什么建议吗?谢谢


Kevin

仅供参考,Windows窗体不支持
MTA线程
主线程。如果成功了,那你就幸运了

我相信您应该能够从STA线程调用DS对象,虽然我对DS不太熟悉,但听起来您正在使用DS,而且在我看来,它对STA最为有效


在这种情况下,为什么不总是从主线程调用
Start
/
Stop
?如果另一个线程需要告诉主线程停止或启动,那么只需让它将任务排队到
任务调度程序。从CurrentSynchronizationContext
在主线程上运行它。

引发了哪个异常?我猜是这样的:“调用线程无法访问这个对象,因为它是另一个线程拥有的。”


在这种情况下,如前所述,请使用正确的调度器进行呼叫。

好的,因此我以前遇到过一个与WPF不太相似的问题,所以请对以下(非常粗糙的)建议持保留态度

下面的方法基本上创建一个完全独立的应用程序线程来运行directshow命令,但告诉directshow使用WPF应用程序中承载的windows窗体控件的句柄

因此,首先我们需要一个虚拟WinForms表单,我们可以使用它调用调用,但它永远不会被呈现:

/// <summary>
/// Just a dummy invisible form.
/// </summary>
private class DummyForm : Form
{

    protected override void SetVisibleCore(bool value)
    {
        //just override here, make sure that the form will never become visible
        if (!IsHandleCreated)
        {
            CreateHandle();
        }

        value = false;
        base.SetVisibleCore(value);
    }
}
因此,一旦创建了虚拟表单(及其线程),就可以调用MTA上的调用 应用程序线程如下:

/// <summary>
/// Blank delegate, used to represent any Invoke or BeginInvoke target method.
/// </summary>
public delegate void InvokeHandler();

//i'm assuming here that DSComponent is a class that all your directshow 
//code is in, and externalControl is the WinForms control you have embedded in 
//your application. 
dumbForm.Invoke(new InvokeHandler(delegate 
{
    //maybe something like this?
    DSComponent.Start(externalControl);
}));

//and to stop it...
dumbForm.Invoke(new InvokeHandler(delegate
{
    DSComponent.Stop();
}));
//to end the separate thread and application loop,
//just close your invisible form
dumbForm.Close();
这种方法的优点是可以将directshow整齐地沙盒到一个单独的线程中。缺点是调用调用的上下文切换,加上另一个应用程序线程的开销。将其嵌入到当前的体系结构中可能会有一些乐趣,但它应该会有所帮助


让我知道你的进展如何,我对这项工作的效果很感兴趣。

发布代码或发布代码说明?我同意第一个。你为什么用DirectShow?WPF可以播放媒体。@Emo-也许他有一个不是文件或普通视频流的视频源?他可能有某种自定义源过滤器,我以前遇到过这些。
//to end the separate thread and application loop,
//just close your invisible form
dumbForm.Close();