我和WPF合作,正在阅读关于STA的材料。两个问题:
1) STA被不同的文章定义为“单线程亲和力”和“单线程单元”。这表示前者:https://msdn.microsoft.com/en-us/library/ms750441(v=vs.110).aspx,表示后者:https://msdn.microsoft.com/en-us/library/ms742522(v=vs.110).aspx
它是哪一个,还是STA可以引用这些相关的概念之一?
2)描述它们之间的关系是否正确:单线程单元是Windows的各个组件所使用的模型,线程亲和力是该模型的一个特征?
谢谢。
发布于 2015-05-26 12:50:30
STA的意思是“单螺纹公寓”。这是一个COM概念,与WPF高度无关。WPF设计者从.NET 1.x中的错误中吸取了教训,许多程序员编写的程序违反了线程安全要求,并且很难修复他们的程序。因此,他们在.NET框架代码中增加了更多的运行时检查,以帮助他们避免麻烦。
虽然它是纯COM概念,但它的基本原理是相当普遍的。通过声明线程STA,您可以保证所编写的代码行为良好。您可以通过运行dispatcher循环(Application.Run)来编写行为良好的代码,而从不阻止在线程上运行的代码。违背这一承诺会导致僵局。
绝大多数.NET类以及您自己编写的大部分代码都是线程不安全的。使这样的代码线程安全有两种基本方法。第一种方法是使用像List<>这样的类,在代码中添加锁语句,以确保List对象一次只能由一个线程访问。
这通常很好,但是类越精细,就越难弄清楚在哪里放置锁语句,这样的锁导致死锁的可能性就越高。然后,您必须保持代码线程安全的唯一其他选项是只对同一个线程进行方法调用。所有的WPF组件都是这样的,您必须从一个工作线程调用Dispatcher.Begin/Invoke()来设置它们的属性或调用它们的方法。现在您可以说对象具有线程关联,它只能从创建它的线程中使用。
WPF设计人员希望添加那些运行时检查,以告诉程序员他使用WPF组件是错误的。组件只能在名为Application.Run()的线程上工作,以便Dispatcher.Begin/Invoke()能够工作。问题是,他们无法判断线程是否要调用Application.Run()。这种情况经常会在以后发生。我们需要一个承诺。
因此,他们借用COM承诺,线程的公寓状态总是被设置,并给出了一个不错的提示,它将如何表现。没有保证,只是一个很好的暗示。WPF应用程序的主线程几乎总是合适的,它是STA,这得益于Main()入口点上的STAThread属性,并且项目模板确保它调用Application.Run()。任务或线程池线程位于MTA中,永远不会调用Application.Run(),因此对于WPF组件来说是一个非常敌对的位置。
它们生成的异常使程序员免于麻烦。请注意,您如何非常容易地抑制此异常。您所要做的就是调用Thread.SetApartmentState()来做出承诺。但当然,你现在没有安全网飞行,WPF不能再告诉你你做错了,现在完全取决于你写正确的代码。您必须调用Application.Run(),即使您通常不想这样做。
发布于 2015-05-26 15:08:25
STAThreadAttribute告诉.NET虚拟机将初始线程的COM单元设置为单线程单元(STA)。
1)这就是STA的意思,A代表的是公寓,而不是亲和力。
这里的主要问题是当处理(外部) COM组件时,通常是GUI控件,例如实例化IE的嵌入式组件的WebBrowser控件,该组件必须处于STA状态。
2)是的,STA隐含线程关联,这是Win32窗口和窗口消息的一般要求。
实际上,您可以使用Main()标记[STAThread],也可以创建一个新线程把它的公寓,然后启动它,只要稍后运行消息循环,比如Application.Run()或WaitHandle上的WaitOne,因为它将使用CoWaitForMultipleHandles。
因此,下面是STAThread属性的含义,或者启动为STA设置的线程:
COINIT_APARTMENTTHREADED调用COINIT_APARTMENTTHREADEDWaitOne和WaitAny将使用消息泵等待,例如CoWaitForMultipleHandles,而不是普通的WaitForSingleObjectEx/WaitForMultipleObjectsExWaitAll,因为底层API将等待所有句柄和消息队列的,因此没有被动的方法等待一组句柄的所有句柄--或--消息队列发布于 2015-05-30 01:14:35
https://stackoverflow.com/questions/30454218
复制相似问题