WPF的单线程单元(STA)

一、问题:

在多线程中不能直接访问UI,调用线程必须为 STA,因为许多 UI 组件都需要

二、原因:

线程模式分为STA(Single Threaded Apartment) 单线程单元 和 MTA 多线程单元(Multi-Threaded Apartment)。任何一个WPF程序,Main方法前必须有一个[STAThread]特性,否则编译会失败。这个特性用来申明该应用程序的初始线程模型为STA,以便和COM兼容。STA是.NET之前,旧的COM年代的词汇。

1.介绍

STA线程单元的运行方式称为Object-per-Client模式,就是在COM库初始化的时候创建一个内存结构,然后让它和调用CoInitialize的线程相关联。这个内存结构针对每个线程都会有一个。支持STA的COM对象只能在创建它的线程里被使用,其它线程如果再创建它就会失败。在STA线程模式中,对线程的所有调用都放到一个队列中,然后逐个处理这些调用。因此,STA线程永远不会同时执行多个方法。STA线程有自己的专有数据,它们不会在线程之间共享数据。这种特征使这一线程模式非常安全,避免了数据的损坏和同步问题。

MTA多线程单元,COM库在进程中创建一个内存结构,这个内存结构在整个进程中只能有一个,然后让它和调用CoInitializeEx的线程相关联。支持MTA的COM对象可以在任意线程里被使用。多个针对它的调用都会被封装成为消息。COM运行时不提供同步,允许多个线程同时调用COM对象。因此,COM对象需要执行它们自己的同步,以防止来自多个线程的同步访问,产生竞争条件。

2.区别

在同一个单元中,单线程单元(STA)访问外部是串行的,在前一个任务完全结束之前不会进行下一个任务,而MTA单元则可以同时运行多个线程,并使用所有可用的共享数据,由于MTA模式支持同时执行多个线程,所以调用者应负责同步多个线程之间的全局数据。

其实STA和MTA是COM规定的一套线程模型,用于保障多线程情况下你的组件代码的同步。比如说有一个COM对象它内部有一个静态变量 gHello,那么这个对象无论生成多少实例对于gHello在内存中只能有一份,那么如果有两个不同的实例在两个线程里面同时去读写它,就有可能出错,所以就要就要有种机制进行同步保护,STA或者MTA就是这种机制。

三、解决方案:

方案一:使用Dispatcher调用,它就是当前UI线程

void authOK(AuthorizationResult auth)  
{  
    App.Current.Dispatcher.Invoke((Action)(() =>  
    {  
        labInfo.Content = "登录成功";  
        btnLogin.IsEnabled = true;  
  
        labUser.Content = auth.User.Name;  
        labToken.Content = auth.AccessToken;  
        loginWin.Close();  
        client.Close();  
    }));  
}

方案二:创建一个STA线程,它不是当前Ui线程,如果有一个waittingBox,它可以很好的避免卡死

     Thread td = new Thread(()=> {
                frmLog fm = new frmLog();
                fm.ShowDialog();
            });
            // 将当前线程设置为单个线程单元(STA)模式方可进行 OLE 调用。
            td.TrySetApartmentState(ApartmentState.STA);<<~~~~~~~~~~~~~~~~~~~~加上这句话就可以解决问题了
            // 设置为后台线程
            td.IsBackground = true;
            // 开启线程
            td.Start();

参考:

https://docs.microsoft.com/zh-cn/windows/win32/com/single-threaded-apartments?redirectedfrom=MSDN

https://blog.csdn.net/fragno/article/details/7982044?utm_medium=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromMachineLearnPai2-1.edu_weight&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromMachineLearnPai2-1.edu_weight

https://blog.csdn.net/MyNameIsXiaoLai/article/details/81332336

https://blog.csdn.net/qq_29111047/article/details/86003556

猜你喜欢

转载自blog.csdn.net/sinat_31608641/article/details/107246065