2012-07-03 33 views
14

我在C#开发过程中遇到过几次这个问题。我会是一个愉快的编码一起,传递对象来来回回线程和什么之间没有,然后突然我得到这个熟悉的错误:为什么有些对象不能从不同的线程访问?

"The calling thread cannot access this object because a different thread owns it."

好了,好了,我之前处理它,尤其是在GUI线程中的对象。你只需要编写一些额外的代码来编程特定的问题。但每遇到一次,我都会遇到一个平凡的对象,但它不喜欢被不同的线程访问。

编辑我在我的原始文章中误解了导致访问异常的对象。它不是IPAddress,而是它的System.Printing.PrintQueue.我用它来获取IP地址。这是您无法从多个线程评估的对象。

我写的所有课程都没有这个问题。我甚至不知道我会如何自己实现这一点。您是否必须保留一个带有创建您的线程ID的成员变量,然后根据每个属性和方法访问权限检查当前线程?这看起来很疯狂。为什么微软会决定......“好的... PrintQueue,绝对不是线程中可共享的,但是这些其他类......他们很好去。”

为什么有些对象被多线程访问阻塞?

+2

想想另一种方法:任何线程都可以访问任何对象,因为它喜欢。现在,该对象必须依赖访问器来正确处理线程问题,或者必须编写一堆额外的代码以确保对于来自多个线程的访问者来说是安全的。选项1不现实,选项2是很多工作。因此,决定采用选项3:禁止来自多个线程的访问器。 – dlev

+1

糟糕的微软。坏。 –

+1

看起来像C#垃圾处理器锁定某些变量,具体取决于它们的使用方式。我从来没有处理过这个问题,但是尝试解决这个问题的一个好方法是,如果你打算在线程之间共享它们,将你的变量放到一个静态的持有者中。一个线程读取其他线程写入。如果两者都需要更改值,则可能需要进行一些锁定以确保写入时没有冲突。 –

回答

3

我觉得这可能会解释得很好,我觉得这个具体与COM有关。

http://msdn.microsoft.com/en-us/library/ms693344%28v=vs.85%29

具体而言。

In general, the simplest way to view the COM threading architecture is to think of all the COM objects in the process as divided into groups called apartments. A COM object lives in exactly one apartment, in the sense that its methods can legally be directly called only by a thread that belongs to that apartment. Any other thread that wants to call the object must go through a proxy.

There are two types of apartments: single-threaded apartments, and multithreaded apartments.

Single-threaded apartments consist of exactly one thread, so all COM objects that live in a single-threaded apartment can receive method calls only from the one thread that belongs to that apartment. All method calls to a COM object in a single-threaded apartment are synchronized with the windows message queue for the single-threaded apartment's thread. A process with a single thread of execution is simply a special case of this model.

Multithreaded apartments consist of one or more threads, so all COM objects that live in an multithreaded apartment can receive method calls directly from any of the threads that belong to the multithreaded apartment. Threads in a multithreaded apartment use a model called free-threading. Calls to COM objects in a multithreaded apartment are synchronized by the objects themselves.

+2

那么你是否暗示System.Printing.PrintQueue对象实际上是一个STA COM对象,这就是为什么它不能被其他线程触及?从查看System.Printing.PrintQueue文档,我如何知道这是一个STA COM对象? – Ultratrunks

+0

有趣的东西。我认为这个http://msdn.microsoft.com/en-us/library/5s8ee185.aspx补充了上面的答案(也解释了为什么Ultratrunks在GUI编程时遇到了这样的问题)。 – jpe

+0

@Ultratrunks我相当肯定,类是COM包装,因为它访问打印队列。但是,我不知道如何知道什么是STA。 MSDN中的类有一个线程安全部分,但我没有看到我期望看到的内容。 –

相关问题