Directshow 过滤器访问线程

发布于 2024-11-14 21:01:07 字数 271 浏览 2 评论 0原文

我使用 directshowlib-2005 用 c# 制作了一个电视播放器。 现在我做了一个方法来搜索可用的频道。

我希望此方法在不同的线程中运行,这样我的 GUI 就不会冻结,但当我尝试在该方法中设置通道时出现错误。尽管我知道它在那里,但它在我的图表中找不到 IAMTVTuner 接口。

如果我不使用不同的线程,该方法工作得很好(但我的 GUI 冻结了一段时间)

我知道它必须对公寓执行某些操作,但是有没有一种方法可以在不同的线程中访问该界面,然后线程在哪里创建了我的图表?

I made a TV-Player in c# using directshowlib-2005.
now I made a method to search for available channels.

I want this method to run in a different thread so my GUI won't freeze, but I get an error when I try to set the channel in the method. It can't find the IAMTVTuner interface in my graph, altough I know it's there.

If I don't use a different thread, the method works just fine (but my GUI freezes for a while)

I know it has to do something with apartments, but is there a way I can acces that interface in a different thread then the thread where created my graph in?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

烦人精 2024-11-21 21:01:07

此问题是因为 DirectShowLib 中的一些 com 类或接口应该仅从创建它的同一线程访问。
所以解决这个问题的办法就是实现 ISynchronizeInvoke ” System.ComponentModel.ISynchronizeInvoke”。

例如,如果您需要访问名为 Media 的类中的方法,该类在多线程模式下内部使用 DirectshowLib 中的一些类或方法,则必须使用以下方式检查是否需要调用InvokeRequired 如果为 true,则必须通过 Invoke 方法访问它。
为了演示如何实现 ISynchronizeInvoke 接口,这里使用了我不久前在 C# 2.0 中开发的代码片段

public abstract class Media : ISynchronizeInvoke
{
        //....

        private readonly System.Threading.SynchronizationContext _currentContext = System.Threading.SynchronizationContext.Current;

        private readonly System.Threading.Thread _mainThread = System.Threading.Thread.CurrentThread;

        private readonly object _invokeLocker = new object();
        //....


        #region ISynchronizeInvoke Members

        public bool InvokeRequired
        {
            get
            {
                return System.Threading.Thread.CurrentThread.ManagedThreadId != this._mainThread.ManagedThreadId;
            }
        }

        /// <summary>
        /// This method is not supported!
        /// </summary>
        /// <param name="method"></param>
        /// <param name="args"></param>
        /// <returns></returns>
        [Obsolete("This method is not supported!", true)]
        public IAsyncResult BeginInvoke(Delegate method, object[] args)
        {
            throw new NotSupportedException("The method or operation is not implemented.");
        }

        /// <summary>
        /// This method is not supported!
        /// </summary>
        /// <param name="method"></param>
        /// <param name="args"></param>
        /// <returns></returns>
        [Obsolete("This method is not supported!", true)]
        public object EndInvoke(IAsyncResult result)
        {
            throw new NotSupportedException("The method or operation is not implemented.");
        }

        public object Invoke(Delegate method, object[] args)
        {
            if (method == null)
            {
                throw new ArgumentNullException("method");
            }

            lock (_invokeLocker)
            {
                object objectToGet = null;

                SendOrPostCallback invoker = new SendOrPostCallback(
                delegate(object data)
                {
                    objectToGet = method.DynamicInvoke(args);
                });

                _currentContext.Send(new SendOrPostCallback(invoker), method.Target);

                return objectToGet;
            }
        }

        public object Invoke(Delegate method)
        {
            return Invoke(method, null);
        }

        #endregion//ISynchronizeInvoke Members

}

This problem is because some com classes or interfaces like in the DirectShowLib should be just accessed from the same thread that it was created on.
So the solution to this problem is to implement ISynchronizeInvoke "System.ComponentModel.ISynchronizeInvoke".

For example if you need to access methods in the class named Media that uses internally some classes or methods from the DirectshowLib in multithreading mode, you have to check if invoke required by using InvokeRequired and if true you have to access it via Invoke method.
To demonstrate how to implement ISynchronizeInvoke interface here is a snippet from a code that I develop some time ago in C# 2.0

public abstract class Media : ISynchronizeInvoke
{
        //....

        private readonly System.Threading.SynchronizationContext _currentContext = System.Threading.SynchronizationContext.Current;

        private readonly System.Threading.Thread _mainThread = System.Threading.Thread.CurrentThread;

        private readonly object _invokeLocker = new object();
        //....


        #region ISynchronizeInvoke Members

        public bool InvokeRequired
        {
            get
            {
                return System.Threading.Thread.CurrentThread.ManagedThreadId != this._mainThread.ManagedThreadId;
            }
        }

        /// <summary>
        /// This method is not supported!
        /// </summary>
        /// <param name="method"></param>
        /// <param name="args"></param>
        /// <returns></returns>
        [Obsolete("This method is not supported!", true)]
        public IAsyncResult BeginInvoke(Delegate method, object[] args)
        {
            throw new NotSupportedException("The method or operation is not implemented.");
        }

        /// <summary>
        /// This method is not supported!
        /// </summary>
        /// <param name="method"></param>
        /// <param name="args"></param>
        /// <returns></returns>
        [Obsolete("This method is not supported!", true)]
        public object EndInvoke(IAsyncResult result)
        {
            throw new NotSupportedException("The method or operation is not implemented.");
        }

        public object Invoke(Delegate method, object[] args)
        {
            if (method == null)
            {
                throw new ArgumentNullException("method");
            }

            lock (_invokeLocker)
            {
                object objectToGet = null;

                SendOrPostCallback invoker = new SendOrPostCallback(
                delegate(object data)
                {
                    objectToGet = method.DynamicInvoke(args);
                });

                _currentContext.Send(new SendOrPostCallback(invoker), method.Target);

                return objectToGet;
            }
        }

        public object Invoke(Delegate method)
        {
            return Invoke(method, null);
        }

        #endregion//ISynchronizeInvoke Members

}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文