2012-07-03 11 views
14

Me he encontrado con este problema varias veces durante el desarrollo en C#. Voy a ser un feliz a lo largo de codificación, los objetos que pasan de aquí para allá entre los hilos y lo que no, entonces, de repente, me sale este error familiar:¿Por qué algunos objetos no son accesibles desde diferentes subprocesos?

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

Pues bien, he tratado con él antes, especialmente con objetos en el hilo de la GUI. Solo tiene que escribir un código adicional para programar alrededor de ese problema específico. Pero de vez en cuando me encuentro con un objeto que, por supuesto, es ordinario, pero que no le gusta ser accedido por diferentes hilos.

EDIT Me equivocaron en mi publicación original sobre el objeto que causaba la excepción de acceso. NO fue IPAddress, en su lugar es System.Printing.PrintQueue. que estaba utilizando para obtener la dirección IP. Este es el objeto que no puede evaluar a partir de más de 1 hilo.

Todas mis clases que he escrito nunca tienen este problema. Ni siquiera sé cómo implementaría esto yo mismo. ¿Tendrías que mantener una variable miembro con la identificación del hilo que te creó, y luego verificar el hilo actual contra eso en cada propiedad y acceso al método? Eso parece una locura. ¿Por qué Microsoft decidiría que ... "OK ... PrintQueue, definitivamente no se puede compartir entre hilos. Pero estas otras clases ... están bien para ir".

¿Por qué se bloquean algunos objetos del acceso a múltiples subprocesos?

+2

Piensa en la alternativa: cualquier hilo puede acceder a cualquier objeto como quiera. Ahora ese objeto tiene que depender del acceso para manejar adecuadamente las preocupaciones de enhebrado, o tiene que escribir un montón de código adicional para garantizar que sea seguro para los usuarios de múltiples hilos. La opción 1 no es realista, y la opción 2 es mucho trabajo. Por lo tanto, se tomó la decisión de ir con la opción 3: no permitir acceso a los usuarios desde múltiples hilos. – dlev

+1

Bad Microsoft. Malo. –

+1

Parece que la eliminación de basura C# bloquea ciertas variables dependiendo de cómo se usan. Nunca he tenido que lidiar con esto, pero una buena forma de intentar solucionar este problema es colocar sus variables en un soporte estático si planea compartirlas entre hilos. Un hilo lee el otro hilo escribe. Es posible que deba hacer algunos bloqueos para asegurarse de que no haya colisiones al escribir si ambos necesitan cambiar el valor. –

Respuesta

3

Creo que esto puede explicar bastante bien las cosas, creo que esto específicamente tiene que ver con COM.

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

específicamente.

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

¿Quiere decir que el objeto System.Printing.PrintQueue es realmente un objeto STA COM y por eso no puede ser tocado por otros hilos? Al consultar la documentación de System.Printing.PrintQueue, ¿cómo puedo saber si se trata de un objeto STA COM? – Ultratrunks

+0

Cosas interesantes. Creo que este http://msdn.microsoft.com/en-us/library/5s8ee185.aspx complementa la respuesta anterior (y también explica por qué Ultratrunks encontró estos problemas junto con la programación de la GUI). – jpe

+0

@Ultratrunks Estoy bastante seguro de que la clase es envoltorio COM ya que accede a la cola de impresión. Sin embargo, no sé cómo saber por adelantado qué es STA. Hay una sección de seguridad de subprocesos para las clases en MSDN, pero no vi lo que esperaba ver allí. –

Cuestiones relacionadas