c#compact框架中的Directshow:Filtergraph'的触发器处理问题;伊梅迪亚事件

c#compact框架中的Directshow:Filtergraph'的触发器处理问题;伊梅迪亚事件,c#,com,compact-framework,directshow,C#,Com,Compact Framework,Directshow,我正在致力于在C#dll中实现directshow功能。我的工作基于C++提供的“CasaCaspAccess”示例,微软提供了Windows Mobile 6 SDK。 事情进行得很顺利(多亏了本网站早些时候的帮助),但我在尝试收听C#land的directshow活动时遇到了一些障碍: 我有一个线程,可以循环侦听dshow事件。它根据此处定义的手动重置事件进行等待(这是在图形初始化结束时定义的:图形已生成,renderstream已调用,controlstream已阻止数据流): 我在这方面

我正在致力于在C#dll中实现directshow功能。我的工作基于C++提供的“CasaCaspAccess”示例,微软提供了Windows Mobile 6 SDK。 事情进行得很顺利(多亏了本网站早些时候的帮助),但我在尝试收听C#land的directshow活动时遇到了一些障碍:

我有一个线程,可以循环侦听dshow事件。它根据此处定义的手动重置事件进行等待(这是在图形初始化结束时定义的:图形已生成,renderstream已调用,controlstream已阻止数据流):

我在这方面遇到了两个相关问题:

  • 当我的dshow事件处理程序循环使用超时0通过IMediaEvent.GetEvent()提取事件时,我在第三次迭代中得到一个“超时超过”hresult(-2147467260)。第三事件触发(和后续错误)在C++示例中不会发生。<李>
  • 如果我忽略上面提到的超时情况,它将不断触发73事件。这会杀死处理器,因为循环基本上从不暂停
  • 当C++示例在预览模式下运行它的图形时,它会得到两个IimeAdvices事件:第一个13,然后73个。之后,它停止触发,直到实际捕获开始。我的C#版本拉了13次,然后是73次,然后又拉了73次,但出现了超时错误

    简言之,似乎DshowRequestMan的第三次触发不应该发生,因为没有真正“获取”的dshowevent,因此超时

    不确定我做错了什么-我在每次迭代中调用“FreeEventParams()”。。。我怀疑ManualResetEvent对象被错误地使用,因为我只是给它的handle属性赋值,但当我使用Pinvoked“WaitForSingleObject”来侦听DshowEventHandle时,也会发生同样的情况。。。我在这一点上感到困惑


    任何想法都将不胜感激。提前谢谢

    您是否确保在获得并处理事件后重置事件

    您的实际等待代码是什么样子的?问题很可能是您正在等待0ms,这基本上意味着“检查事件并立即返回”。如果您希望它在等待时阻塞(如使用wait_INFINITE的本机调用),则需要传入System.Threading.Timeout.INFINITE(实际上是-1)

    如果您希望检查线程周期性地产生(这比无限等待安全得多,并且实际上会允许您的应用程序关闭),那么您需要检查等待的返回,如果是超时(0x80004004),则只需返回并再次等待:

    while(!shutdown)
    {
      if(DshowRequestMan.WaitOne(1000))
      {
        // handle the event
      }
    }
    

    以下是我的过滤器图事件处理代码:

    while (!_stopReceivingEvents) {
        IntPtr eventHandle;
        var hr = _mediaEvent.GetEventHandle(out eventHandle);
        DsError.ThrowExceptionForHR(hr);
    
        //NOTE: Do not close the event handle, because it is used internally by the filter graph
        using (var safeWaitHandle = new SafeWaitHandle(eventHandle, false)) {
            using (var waitHandle = new AutoResetEvent(false) {SafeWaitHandle = safeWaitHandle}) {
                if (WaitHandle.WaitAll(new[] {waitHandle}, 500)) {
                    //receive all available events
                    do {
                        EventCode eventCode;
                        IntPtr param1;
                        IntPtr param2;
                        hr = _mediaEvent.GetEvent(out eventCode, out param1, out param2, 500);
                        _mediaEvent.FreeEventParams(eventCode, param1, param2);
    
                        if (hr == 0) {
                            switch (eventCode) {
                                //add handling code here
                            }
                        }
                    } while (hr == 0);
                }
            }
        }
    }
    

    在循环的底部调用-DshowRequestMan.Reset()。我也试过了,没有调用Reset-两个都有相同的结果。谢谢你的代码块+1。我有一个与此相关的问题。我将您的代码粘贴在
    hr=mediaControl.Run()行之后因为它是一个
    while
    所以代码在
    内部执行,而
    和预览窗口永远不会显示。因此,我将
    while
    循环包装在
    System.Threading.Tasks.Task.Factory.StartNew(()=>{//while loop})中。因为我是
    Directshow
    .NET
    的新手,所以我想问一下,在
    任务
    中保持
    是安全的,或者你会建议的任何其他选项?有什么帮助吗?对不起,我不太清楚这段代码是做什么的。那是很久以前的事了。
    
    while (!_stopReceivingEvents) {
        IntPtr eventHandle;
        var hr = _mediaEvent.GetEventHandle(out eventHandle);
        DsError.ThrowExceptionForHR(hr);
    
        //NOTE: Do not close the event handle, because it is used internally by the filter graph
        using (var safeWaitHandle = new SafeWaitHandle(eventHandle, false)) {
            using (var waitHandle = new AutoResetEvent(false) {SafeWaitHandle = safeWaitHandle}) {
                if (WaitHandle.WaitAll(new[] {waitHandle}, 500)) {
                    //receive all available events
                    do {
                        EventCode eventCode;
                        IntPtr param1;
                        IntPtr param2;
                        hr = _mediaEvent.GetEvent(out eventCode, out param1, out param2, 500);
                        _mediaEvent.FreeEventParams(eventCode, param1, param2);
    
                        if (hr == 0) {
                            switch (eventCode) {
                                //add handling code here
                            }
                        }
                    } while (hr == 0);
                }
            }
        }
    }