WPF主题:“COM对象,它已经从它的基础RCW分离,不能使用。”(WPF Thread: “COM

2019-11-03 22:15发布

我收到以下错误:

"COM object that has been separated from its underlying RCW cannot be used."

我相信这个问题是因为COM对象被不叫已经创建的线程上 - STA。 我试图实现IDisposable,但它并没有为我工作。

有一对夫妇处理类似的问题,但它仍然没有解决我的问题帖子:

它是安全调用从一个终结的RCW? 释放Excel对象在析构函数

任何人都可以发布一个例子/解释如何COM对象应该被正确地从另一个线程访问?

这里是最小的代码显示问题:

using System;
using System.Threading;

namespace Test.ComInterop
{
    public class Program
    {
        MyCom _myCom;

        [STAThread]
        static void Main( string[] args )
        {
            new Program();
        }

        public Program()
        {
            _myCom = new MyCom();

            // this method call works
            string version = _myCom.ComMethod();

            StartThread();
        }

        private void StartThread()
        {
            Thread t = new Thread( UIRun );
            t.SetApartmentState( ApartmentState.STA );
            t.Start();
        }

        void UIRun()
        {
            TestUI window = new TestUI();
            window.Show();

            // this method call fails
            window.Title = _myCom.ComMethod();

            window.Closed += ( sender2, e2 ) 
                => window.Dispatcher.InvokeShutdown();

            System.Windows.Threading.Dispatcher.Run();
        }
    }

    class MyCom
    {
        private dynamic _com;
        public MyCom()
        {
            _com = Activator.CreateInstance(
                Type.GetTypeFromProgID( "Excel.Application" ) );
        }

        public string ComMethod()
        {
            return (string) _com.Version;
        }
    }    
}

Answer 1:

问题是你的程序的启动线程。 它创建的COM对象,启动一个线程,然后退出 。 作为该主线程的清理过程中,.NET调用CoUninitialize(),这就是COM对象的末尾。 收到这个错误是预期的结果。

有没有在让你的主启动线程退出一样,只是没有任何意义。 让它做现在自己的线程所做的工作,问题就迎刃而解了。



Answer 2:

通常这是因为底层的COM对象已经从包装中释放 - 这种情况,当你通过手动Marshal.Release释放或托管包装配置。 使用了错误的线程上只会造成COM对象的任何调用它创建的线程上实际发生 - 我被这在过去的刺痛,它具有执行线程的亲和力。

你似乎并没有被处置包装的,但我不知道什么是动态变化的影响就越大。

你试图改变你的线程公寓状态MTA?



Answer 3:

对不起,也许没有直接回答你的问题。 这仅仅是用不同的方式处理它的建议。 希望能帮助到你。

与Excel的COM互操作有相当多的陷阱 - 不直接相关的COM我想,但到Excel COM是如何实现的。

我挣扎了很多与Excel文件(也MsProject)COM互操作。 对于Excel唯一的好解决办法是从创建处理整个Excel的通信直至终止一个专门的线程。 有一些设计上的缺陷了Excel的API中。 有些方法调用不无状态的,这意味着两个线程将有一个很难做出的东西的工作。 这将是更安全的委派所有的通信一个线程和处理与其他线程自己的通信。

除了这一点,你正在使用的通信线也必须具有EN / US文化( LCID问题 )。 这通常会导致在其他信息:

旧的格式或无效的类型库

但可能是有用的,你就知道了。



Answer 4:

请尝试将MYCOM类继承DispatcherObject的。 当您启动您的其他线程,做一个_myCom.Dispatcher.Run()。 当你想谈谈你的COM对象,只是做一个_myCom.Dispatcher.BeginInvoke / Invoke的。



文章来源: WPF Thread: “COM object that has been separated from its underlying RCW cannot be used.”