2012-02-17 22 views
6

Estoy enfrentando numerosos bloqueos en una aplicación que tiene muchos subprocesos múltiples.¿CWnd :: GetSafeHwnd() y CWnd :: m_hWnd ThreadSafe?

la lectura de estos MSDN page, technical note y this article on TLS, me han entendido que los objetos CWnd se asignan a HWND en el TLS que es un acceso de memoria dependendent hilo.

Iba a desacoplar todo lo que se parece a CWnd thread-remote access, y transformarlo en referencias HWND y luego utilizar :: PostMessage como puerto de comunicación. (Y representa una gran cantidad de trabajo por lo que veo en el código actual por el momento, de hecho estuve desarrollando una solución, eso tomará mucho tiempo, así que tuvimos que discutir al respecto).

Pero uno de mis colegas realmente insistió profundamente en que simplemente mantenga el CWnd * en los hilos extranjeros, adopte la política :: PostMessage bien, pero use CWnd :: GetSafeHwnd() o el pMyCWnd-> m_hWnd en los hilos extranjeros para recuperar el HWND nativo.

He estado argumentando que ninguna parte he visto que el GetSafeHwnd() es multi-hilo, y que el CWnd objet estar en el TLS, su valor en otro hilo es diferente. ¿Estoy equivocado? MSDN claramente usa el término "Resultados inesperados".

¿Cuál es su punto de vista, a pesar de llamar a CWnd :: GetSafehwnd() o pMyCWnd-> m_hWnd en hilos externos desde el hilo del creador?

Tiene cualquier documentación de MSDN que indique que esto es seguro o no.

Respuesta

7

CWnds no están asignados a HWND; Los HWND se asignan a CWnds, y esto sucede por subproceso. El objeto CWnd no está en TLS (¿cómo funcionaría eso?) Sino que se crean objetos CWnd temporales por subproceso.

Acceder a temporal CWnd el objeto del subproceso incorrecto es definitivamente una mala idea (por las razones descritas por Mark Ransom).

Sin embargo, si tiene un objeto CWnd permanente (que representa la ventana principal de su aplicación, por ejemplo), una vez creado, no hay ningún problema para acceder al miembro m_hWnd desde cualquier hilo. Es solo un valor en la memoria que nunca cambia.

Si esto te molesta (porque no está documentado explícitamente), simplemente haz una copia del HWND y deja que los hilos accedan a eso.

P.S. Here's the article you linked to en inglés.

1

Si tiene una aplicación multiproceso donde varios hilos intentan acceder a los HWND a la vez, me parece que tiene un problema de diseño. ¿No puedes restringir tus hilos para hacer cálculos y manejar problemas de UI en el hilo principal? Ese es el diseño típico de una buena aplicación multiproceso.

+0

Buen consejo, pero no puedo recodificar todo, muchos LOC, y tiene más de 10 años, hay una gran historia que no puedo borrar :-) –

+0

Bueno, tu pregunta es básicamente " Tengo que hacer esto extremadamente inseguro, ¿es seguro? Y la respuesta es probablemente que "nada lo hará seguro". Puede hacerlo * más seguro * hasta cierto punto, pero dudo que se pueda hacer sin problemas en el diseño actual. – StilesCrisis

+0

(Por cierto, me puedo relacionar. También trabajo en una base de código MFC de 10 años. Gracias a Dios que no tenemos hilos, los codificadores originales no fueron lo suficientemente inteligentes como para haberlo conseguido). – StilesCrisis

4

GetSafeHwnd es simplemente un contenedor que comprueba si this es NULL, devuelve m_hWnd si no es así y NULL si lo es. No será más seguro que el propio m_hWnd.

Cuando crea un CWnd * temporal, MFC lo destruirá en un punto que considere seguro, como la próxima pasada a través del bucle de mensajes. Si tiene varios subprocesos usando MFC, su objeto temporal podría destruirse mientras aún lo esté usando. Nada de lo que pueda hacer con su hilo detectará este error.

+0

son todos los temporales de CWnd * o no? Me refiero a la única CWnd * creada en el hilo del creador al instanciar la ventana, ¿es temporal también? (Quiero decir, no los que se computaron a través de CWnd :: FromHandle()) –

Cuestiones relacionadas