C# 使用COM对象锁定UI的后台工作程序仍然

C# 使用COM对象锁定UI的后台工作程序仍然,c#,multithreading,backgroundworker,threadpool,alm,C#,Multithreading,Backgroundworker,Threadpool,Alm,所以我不知道怎么问这个问题,这可能是我在任何地方都找不到答案的原因之一 因此,我的设置是,我有一个类 public class Connection { public static event EventHandler LogggedIn; public static TDConnection TDC {get;set;} public string Authenticate(){...} public static void Login() {

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

因此,我的设置是,我有一个类

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());
    }
}
在我的主类中,我实例化了一个新连接并调用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;
    }
我不想这样做,因为我已经登录了,这样做需要额外的时间

我已经尝试将Connection.TDC与_bw.RunorkerAsync(Connection.TDC)一起传入,但显然这也不起作用


是否有任何方法可以使用已建立的连接,并且在连接时不阻止UI

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

它通过自动封送从工作线程到创建对象的线程的方法调用来实现。您可以看到这一点,您在主线程上创建了TDC对象。因此,当您从BackgroundWorker调用它时,它仍然会在主线程上执行调用


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

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

它通过自动封送从工作线程到创建对象的线程的方法调用来实现。您可以看到这一点,您在主线程上创建了TDC对象。因此,当您从BackgroundWorker调用它时,它仍然会在主线程上执行调用


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

这里没有UI代码。您是否从UI线程调用此类上的方法,该方法将一直阻止,直到后台工作程序完成?您的WorkerReportsProgress和Cancellation设置有误导性(因为未使用)。抱歉。我正在使用连接。在Winform按钮单击事件处理程序中登录。由于连接将在一个线程中打开,因此我已连接了一个事件处理程序,以便在连接建立后触发。因为它是从我的Winform调用的,所以它会阻塞我的UI。这里没有UI代码。您是否从UI线程调用此类上的方法,该方法将一直阻止,直到后台工作程序完成?您的WorkerReportsProgress和Cancellation设置有误导性(因为未使用)。抱歉。我正在使用连接。在Winform按钮单击事件处理程序中登录。由于连接将在一个线程中打开,因此我已连接了一个事件处理程序,以便在连接建立后触发。因为它是从我的Winform调用的,所以它会阻塞我的UI。你知道我可以看一个很好的例子吗?我没有听说过SetApartmentState,乍一看,我还没有找到太多有用的文章。也许我遗漏了一些东西,但将其切换到STA线程意味着它仍将被阻止,不是吗?也许我不理解你的例子,但是如果我在STA线程内部调用Connecton.TDC.ConnectToProject,它仍然会阻塞正确吗?当然。问题是阻塞发生在主线程以外的线程上。所以基本上,如果调用登录线程后有更多代码要执行,它会在登录时执行吗?我需要的是UI不被阻止。如果没有办法,我想我会继续我的原创作品。谢谢你的帮助!你知道一个很好的例子吗?我没有听说过SetApartmentState,乍一看,我还没有找到太多有用的文章。也许我遗漏了一些东西,但将其切换到STA线程意味着它仍将被阻止,不是吗?也许我不理解你的例子,但是如果我在STA线程内部调用Connecton.TDC.ConnectToProject,它仍然会阻塞正确吗?当然。问题是阻塞发生在主线程以外的线程上。所以基本上,如果调用登录线程后有更多代码要执行,它会在登录时执行吗?我需要的是UI不被阻止。如果没有办法,我想我会继续我的原创作品。谢谢你的帮助!