2

所以我不知道如何问这个问题,这可能是我在任何地方都找不到答案的原因之一。

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

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());
    }
}

在我的主类中,我实例化了一个新的 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;
    }

我不希望这样做,因为我已经登录并且需要额外的时间来执行此操作。

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

有什么方法可以使用已经建立的连接并且在连接时不阻塞 UI?

4

1 回答 1

6

这在 COM 对象中很常见。就像 .NET 类一样,许多 COM coclass 也不是线程安全的。在 .NET 中,如果您以线程不安全的方式使用 .NET 类,您将自食其果。不是在 COM 中,它保证以线程安全的方式使用标榜自己不是线程安全的 coclass。

它通过自动将工作线程的方法调用编组到创建对象的线程来实现。您可以看到它的去向,您在主线程上创建了 TDC 对象。所以当你从BackgroundWorker调用它时,它仍然会在主线程上执行调用。

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

于 2012-08-31T17:54:25.937 回答