c++ - pantallas - limpiar pantalla en c mac
¿Inicialización y limpieza de COM apropiadas en la granularidad de nivel de función? (1)
Es una práctica terrible y fundamentalmente errónea. Lo que importa mucho es el valor del segundo argumento (dwCoInit). Debe ser COINIT_APARTMENTTHREADED, a menudo abreviado como STA, o COINIT_MULTITHREADED (MTA). Esta es una promesa que usted hace, el estilo de "cruza el corazón-esperanza-para-morir". Si rompes la promesa, el programa morirá. Por lo general, mediante el bloqueo, al no obtener los eventos esperados o tener una perfusión inaceptablemente lenta.
Cuando selecciona STA, promete que el subproceso se comporta bien y puede admitir componentes COM que no son seguros para subprocesos. Cumplir con esa promesa requiere que el hilo bombee un ciclo de mensajes y nunca bloquee. El comportamiento común de un hilo que admite una GUI, por ejemplo. La gran mayoría de los componentes COM no son seguros para subprocesos.
Cuando selecciona MTA, no promete ningún tipo de soporte. El componente ahora debe valerse por sí mismo para mantenerse a salvo de subprocesos. A menudo se realiza automáticamente al tener la infraestructura COM creando un hilo por sí mismo para darle al componente un hogar seguro. Un detalle adicional que debe tener en cuenta es ordenar el puntero de la interfaz, requiere la función auxiliar CoMarshalInterThreadInterfaceInStream () o la interfaz IGlobalInterfaceTable más conveniente. Esto asegura que se crea un proxy que se encarga del cambio de contexto de hilo requerido.
MTA parece conveniente, pero no sin consecuencias, una simple llamada de obtención de propiedades puede tardar tanto como x10000 más tiempo. Gastos generales impuestos por los conmutadores de contexto de subprocesos y la necesidad de copiar cualquier argumento y el valor de retorno en los marcos de pila. Y al calcular el puntero de la interfaz puede fallar fácilmente, los autores de los componentes COM a menudo no proporcionan el proxy / stub necesario o lo omiten intencionalmente porque es muy difícil o caro copiar los datos.
El punto clave es que la elección entre STA y MTA nunca puede ser hecha por una biblioteca. No sabe frijoles sobre el hilo, no creó ese hilo. Y no puede saber si el hilo bombea un bucle de mensaje o bloques. Ese es todo el código que está completamente fuera del alcance de la biblioteca. De lo contrario, la razón exacta por la que la infraestructura COM necesita saber esto también, tampoco puede hacer suposiciones sobre el hilo.
La elección debe hacerse mediante el código que creó e inicializó el hilo, invariablemente la aplicación en sí. A menos que la biblioteca cree un hilo con el fin de hacer las llamadas seguras. Pero luego con la consecuencia de que el código siempre es lento. Le recuerda a la persona que llama de su biblioteca que no lo hizo correctamente al devolver el inevitable código de error CO_E_NOTINITIALIZED.
Fwiw, esto es algo que se ve en .NET Framework. El CLR siempre llama a CoInitializeEx () antes de que un hilo pueda ejecutar cualquier código administrado. Sigue siendo una opción que debe realizar el programador de la aplicación, o más típicamente la plantilla del proyecto, con el atributo [STAThread] en Main () o la llamada a Thread.SetApartmentState () para un hilo de trabajo.
Considere escribir una función personalizada reutilizable que dentro de su cuerpo crea objetos COM y llama a métodos para algunas interfaces COM. Para que esto funcione correctamente, se debe CoUninitialize
CoInitializeEx
y las API CoUninitialize
coincidentes.
Llamar a esas API de inicialización y limpieza COM dentro del cuerpo de la función ocultaría un detalle de implementación COM a la persona que llama, y también eliminaría una carga de la persona que llama.
Pero, ¿se considera que CoInitializeEx
y el CoUninitialize
coincidente dentro del cuerpo de la función son una buena práctica de codificación?
¿Llamar a esas funciones COM init / cleanup en el nivel de granularidad de función implica demasiada sobrecarga para cada llamada de función?
¿Hay otros inconvenientes en este diseño?