的ApartmentState傻瓜 [英] ApartmentState for dummies

查看:184
本文介绍了的ApartmentState傻瓜的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我只是纠正的错误使用这样的:

I just corrected a bug using this:

_Thread.SetApartmentState(ApartmentState.STA);

现在我想明白这意味着什么,以及为什么它的作品!

Now I'd like to understand what it means, and why it works!

推荐答案

COM是.NET的外公。他们有pretty的崇高目标有了它,COM的做,但是.NET完全跳过正在提供线程担保一类的事情之一。 COM类可以发布有什么样的线程样的要求。和COM的基础设施可以确保满足这些要求。

COM is the grand father of .NET. They had pretty lofty goals with it, one of the things that COM does but .NET completely skips is providing threading guarantees for a class. A COM class can publish what kind of threading requirements it has. And the COM infrastructure makes sure those requirements are met.

这是在.NET中完全不存在。您可以使用问答LT;>对象,例如在多线程,但如果你不锁正确,你将有一个讨厌的错误在你的code,这是非常难以诊断

This is completely absent in .NET. You can use a Queue<> object for example in multiple threads but if you don't lock properly, you'll have a nasty bug in your code that is very hard to diagnose.

的具体细节是太大,不适合在后。我将专注于你的问题的细节。创建COM对象的线程必须告诉COM它希望提供给那些受限制的线程选择COM类什么样的支持。这些类的绝大多数只支持所谓的公寓线程,它们的接口方法只能安全地从创建的实例在同一个线程调用。换句话说,他们宣布:我不支持任何线程,请照顾的永远的从错误的线程中调用了我。即使客户端code实际的没有的从另一个线程调用它。

The exact details of COM threading are too large to fit in a post. I'll focus on the specifics of your question. A thread that creates COM objects has to tell COM what kind of support it wants to give to COM classes that have restricted threading options. The vast majority of those classes only support so-called Apartment threading, their interface methods can only safely be called from the same thread that created the instance. In other words, they announce "I don't support threading whatsoever, please take care of never calling me from the wrong thread". Even if the client code actually does call it from another thread.

有两种,STA(单线程单元)和MTA。它被指定在CoInitializeEx的()调用一个函数,它的必须的由做任何事情与COM任何线程调用。在CLR会自动调用那个无论何时启动一个线程。对于你的程序的主启动线程,它得到的值从[STAThread]或[MTAThread]在您的Main()方法的属性传递。默认值是MTA。对于你自己创建的线程它是由您的来电SetApartmentState()确定。默认值是MTA。线程池线程总是的MTA,这是不能改变的。

There are two kinds, STA (Single Threaded Apartment) and MTA. It is specified in the CoInitializeEx() call, a function that must be called by any thread that does anything with COM. The CLR makes that call automatically whenever it starts a thread. For the main startup thread of your program, it gets the value to pass from the [STAThread] or [MTAThread] attribute on your Main() method. Default is MTA. For threads that you create yourself it is determined by your call to SetApartmentState(). Default is MTA. Threadpool threads are always MTA, that cannot be changed.

有很多的code在Windows中,需要一个STA。著名的例子是剪贴板,拖动+拖放及外壳对话框(如打开文件对话框)。一个WPF或Windows窗体项目的UI线程应始终STA一样,创建一个窗口中的任何线程。

There's lots of code in Windows that requires an STA. Notable examples are the Clipboard, Drag + Drop and the shell dialogs (like OpenFileDialog). The UI thread of a WPF or Windows Forms project should always be STA, as does any thread that creates a window.

你让你的线程是STA然而,承诺COM的确实的要求你按照单线程公寓的合同。他们是pretty的僵硬,你可以得到pretty的难以诊断的麻烦,当你违反了合同。要求你的永远的阻塞线程任何的时间和你抽消息循环。后者要求由一个WPF或的WinFormsUI线程谋面,但你需要照顾它自己,如果你创建自己的STA线程。常见的诊断为打破合同僵局。

The promise you make to COM that your thread is STA however does require you to follow the single-thread apartment contract. They are pretty stiff and you can get pretty hard to diagnose trouble when you break the contract. Requirements are that you never block the thread for any amount of time and that you pump a message loop. The latter requirement is met by a WPF or Winforms' UI thread but you will need to take care of it yourself if you create your own STA thread. The common diagnostic for breaking the contract is deadlock.

有相当多的支持,内置的CLR,以支持这些要求顺便说一句,帮助您保持麻烦。在锁定的语句,例如将泵消息循环当一个STA线程阻塞。大多数同步类做的一样好,互斥是一个明显的例外。但是,这仅需要护理的永远块的要求,你仍然需要创建自己的消息循环。 Application.Run()在WPF和的WinForms。

There's quite a bit of support built-in the CLR to support these requirements btw, helping you to keep out of trouble. The lock statement for example will pump a message loop when it blocks on an STA thread. Most synchronization classes do as well, Mutex being a notable exception. This however only takes care of the never-block requirement, you still need to create your own message loop. Application.Run() in both WPF and Winforms.

我有previously贡献,其中包含有一个消息循环,以保持COM快乐的意义更细节的答案。您会在这里找到职务。

I've previously contributed an answer that contains more details about the significance of having a message loop to keep COM happy. You'll find the post here.

这篇关于的ApartmentState傻瓜的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆