MDA de invalidApartmentStateChange
Nota:
Este artículo es específico de .NET Framework. No se aplica a implementaciones más recientes de .NET, incluidas .NET 6 y versiones posteriores.
El Asistente para la depuración administrada (MDS) invalidApartmentStateChange
se activa por cualquiera de estos dos problemas:
Se realiza un intento de cambiar el estado de contenedor COM de un subproceso que ya se ha inicializado por COM a un estado de contenedor diferente.
El estado de contenedor COM de un subproceso cambia de forma inesperada.
Síntomas
El estado de contenedor COM de un subproceso no es el que se solicitó. Esto puede provocar que se usen servidores proxy para los componentes COM que tienen un modelo de subprocesos diferente del actual. A su vez, esto puede hacer que se produzca una InvalidCastException al llamar al objeto COM a través de interfaces que no están configuradas para la serialización entre contenedores.
El estado de contenedor COM del subproceso es diferente de lo esperado. Esto puede causar una excepción COMException con un valor HRESULT de RPC_E_WRONG_THREAD, así como una excepción InvalidCastException cuando se realizan llamadas en un contenedor RCW. Esto puede hacer que varios subprocesos tengan acceso al mismo tiempo a algunos componentes COM de un único subproceso, lo que puede provocar daños o pérdida de datos.
Causa
El subproceso se inicializó previamente a un estado de contenedor COM diferente. Tenga en cuenta que el estado de contenedor de un subproceso se puede establecer de forma explícita o implícita. Las operaciones explícitas incluyen la propiedad Thread.ApartmentState y los métodos SetApartmentState y TrySetApartmentState. Un subproceso creado mediante el método Start se establece implícitamente en MTA a menos que se llame a SetApartmentState antes de iniciar el subproceso. El subproceso principal de la aplicación también se inicializa implícitamente en MTA a menos que se especifique el atributo STAThreadAttribute en el método principal.
El método
CoUninitialize
(o el métodoCoInitializeEx
) con un modelo de simultaneidad diferente se llama en el subproceso.
Solución
Establecer el estado de contenedor del subproceso antes de que empiece a ejecutarse, o aplicar el atributo STAThreadAttribute o MTAThreadAttribute al método principal de la aplicación.
Para la segunda causa, idealmente el código que llama al método CoUninitialize
debe modificarse para retrasar la llamada hasta que el subproceso esté a punto de terminar y no haya ningún RCW, y sus componentes COM subyacentes sigan en uso en el subproceso. Pero si no es posible modificar el código que llama al método CoUninitialize
, entonces no deben usarse contenedores RCW desde los subprocesos sin inicializar de esta manera.
Efecto en el Runtime
Este MDA no tiene ningún efecto en el CLR.
Output
El estado de contenedor COM del subproceso actual y el estado que el código intentaba aplicar.
Configuración
<mdaConfig>
<assistants>
<invalidApartmentStateChange />
</assistants>
</mdaConfig>
Ejemplo
En el ejemplo de código siguiente se muestra una situación que puede activar este MDA.
using System.Threading;
namespace ApartmentStateMDA
{
class Program
{
static void Main(string[] args)
{
Thread.CurrentThread.SetApartmentState(ApartmentState.STA);
}
}
}