使用COM对象的后台工作者仍然锁定UI

Sme*_*iff 1 c# multithreading backgroundworker alm threadpool

所以我不知道如何提出这个问题,可能是我在任何地方找到问题的原因之一.

所以我的设置是我有一堂课

public class Connection
{
    public static event EventHandler LogggedIn;
    public static TDConnection TDC {get;set;}
    public string Authenticate(){...}
    public static void Login()
    {
        if (Connection.TDC.Connected)
        {
            _bw = new BackgroundWorker
            {
                WorkerReportsProgress = true,
                WorkerSupportsCancellation = true
            };
            _bw.DoWork += ConnectToProject_DoWork;
            _bw.RunWorkerCompleted += ConnectToProject_RunWorkerCompleted;

            _bw.RunWorkerAsync(Connection.TDC);
        }
    }

    private static void ConnectToProject_DoWork(object o, DoWorkEventArgs e)
    {
        Connection.TDC.ConnectProjectEx(Connection.Domain, Connection.Project, Connection.UserName, Utilities.Encryption.AESEncryption.Decrypt(Connection.Password, "fsd*#(dfs(((>>>???fdjs"));
    }

    private static void ConnectToProject_RunWorkerCompleted(object o, RunWorkerCompletedEventArgs e)
    {
        LogggedIn(null, new EventArgs());
    }
}
Run Code Online (Sandbox Code Playgroud)

在我的主类中,我实例化一个新的Connection并调用Login,它在TDConnection中打开一个与ALM的新连接.在我的线程中,我想在我的线程中使用这个已经打开的连接.根据我的阅读,如果我这样做,我的UI将阻止因为我在UI线程上使用成员的方法,即使我在后台工作者内部.

我发现这样做的一个解决方案:

private static void ConnectToProject_DoWork(object o, DoWorkEventArgs e)
    {
        TDConnection conn = new TDConnection();
        conn.InitConnectionEx(QCURL);

        conn.Login();

        conn.ConnectProject();

        e.Result = conn;
    }
Run Code Online (Sandbox Code Playgroud)

我不想这样做,因为我已经登录了,这需要额外的时间来完成.

我已经尝试使用_bw.RunorkerAsync(Connection.TDC)传递Connection.TDC,但这显然不起作用.

有什么方法可以使用已经建立的连接,而不是在连接时阻止UI?

Han*_*ant 5

这在COM对象中很常见.就像.NET类一样,许多COM coclass都不是线程安全的.在.NET中,如果以线程不安全的方式使用.NET类,则可以自己动手.不在COM中,它保证了一个宣称自己不是线程安全的coclass将以线程安全的方式使用.

它通过自动封送从工作线程到创建对象的线程的方法调用来完成.你可以看到它在哪里,你在主线程上创建了TDC对象.所以,当你从BackgroundWorker的调用它,它将仍然执行主线程中调用.

解决此问题的唯一方法是在您使用它的同一个线程上创建对象.这通常也意味着您不能使用BackgroundWorker,您可能需要创建一个Thread并调用其SetApartmentState()方法将其切换到STA.