Directshow filter access threading

2020-02-06 10:55发布

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?

1条回答
聊天终结者
2楼-- · 2020-02-06 11:28

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

}
查看更多
登录 后发表回答