WPF 线程:“无法使用已与其底层 RCW 分离的 COM 对象。”

Mik*_*ail 1 c# com wpf multithreading interop

我收到以下错误:

"COM object that has been separated from its underlying RCW cannot be used."
Run Code Online (Sandbox Code Playgroud)

我确信问题是因为 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;
        }
    }    
}
Run Code Online (Sandbox Code Playgroud)

Han*_*ant 5

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

让主启动线程像这样退出是没有意义的。让它完成现在由您自己的线程完成的工作,问题就解决了。