La variable externa no está disponible para hustar hasta que se realiza la llamada de bloqueo ...
-
27-10-2019 - |
Pregunta
Tengo dos archivos de código, uno contiene mi WinMain()
función, y todas las funciones relacionadas con mi ventana de diálogo principal. El otro contiene una devolución de llamada de hilo y funciones variables relacionadas con mi programa. He definido HWND hWnd = NULL
como una variable global en maindlg.cpp y definida extern HWND hWnd
en otro.cpp (que contiene la devolución de llamada del hilo). El hilo se crea cuando el WM_INITDIALOG
El mensaje se envía a la ventana. Dentro de la devolución de llamada del hilo, el hWnd
La variable es nula hasta que se realiza un largo funcionamiento, luego después de eso está disponible.
Maindlg.cpp
HWND hWnd = NULL;
HANDLE hListenThread = NULL;
DWORD WINAPI ListenThread( LPVOID lpvParam );
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow )
{
/* ... */
if( NULL == (hWnd=CreateDialog( hInstance, MAKEINTRESOURCE(IDD_MAINDLG), NULL, (DLGPROC)WndProc)) )
{
MessageBox( NULL, "Error creating the main dialog!", NULL, MB_OK | MB_ICONERROR );
return -1;
}
MSG msg;
while( GetMessage(&msg,NULL,0,0) && IsWindow(hWnd) )
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
}
BOOL CALLBACK WndProc(HWND hWndDlg, UINT Message, WPARAM wParam, LPARAM lParam)
{
switch(Message)
{
case WM_INITDIALOG:
{
DWORD dwListenThreadId = NULL;
/* referencing hWnd here works fine... */
/* ... */
hListenThread = CreateThread(
NULL,
0,
ListenThread,
hWndDlg,
0,
&dwListenThreadId);
/* ... */
} break;
}
return false;
}
Otro.cpp
extern HWND hWnd;
DWORD WINAPI ListenThread( LPVOID lpvParam )
{
if( hWnd == NULL )
MessageBox( NULL, "hWnd == NULL", NULL, MB_OK | MB_SYSTEMMODAL );
if( hWnd != NULL )
MessageBox( NULL, "hWnd != NULL", NULL, MB_OK | MB_SYSTEMMODAL );
return 0;
}
Ambos cuadros de mensajes en el ListenThread
La devolución de llamada se muestra cuando se inicia la aplicación. ¿Alguien puede decirme por qué está sucediendo esto? ¿Hay algo que pueda hacer para arreglar esto además de hacer? while( hWnd == NULL );
al comienzo de mi ListenThread
?
Solución
los WM_INITDIALOG
Se produce un mensaje antes de CreateDialog
devoluciones y hWnd
no está configurado hasta CreateDialog
devoluciones. Por lo tanto, el hilo comienza a ejecutarse antes de creatialog devuelve y establece el global hWnd
variable.
Para que puedas arreglar esto moviendo tu creación de hilo desde el WM_INITDIALOG
mensaje justo después de la devolución de CreateDialog
.
Pero no necesita hacer eso porque el código no requiere el global hWnd
variable. Ya está pasando el mango de la ventana de sus cuadros de diálogo como parámetro al procedimiento de inicio de subproceso. Así que solo lanza el LPVParam a un HWND
Y usa eso. Eso le permitirá deshacerse de su variable global, lo cual es una mala práctica de usar.
Otro.cpp
DWORD WINAPI ListenThread( LPVOID lpvParam )
{
HWND hWnd= (HWND)lpvParam;
if( hWnd == NULL )
MessageBox( NULL, "hWnd == NULL", NULL, MB_OK | MB_SYSTEMMODAL );
if( hWnd != NULL )
MessageBox( NULL, "hWnd != NULL", NULL, MB_OK | MB_SYSTEMMODAL );
return 0;
}
Otros consejos
los WM_INITDIALOG
el mensaje se emite a WndProc()
desde el interior de CreateDialog()
en sí, no por DispatchMessage()
. Esto se establece tanto en el CreateDialog()
documentación. Su hWnd
La variable no se asigna hasta después CreateDialog()
salidas. Si su hilo comienza a funcionar antes CreateDialog()
Salidas (dependiendo de la programación de tareas, eso no es una garantía), su primera MessageBox()
se llama. Mientras que la MessageBox()
Esta corriendo, CreateDialog()
tiene tiempo para salir y asignar la variable, por lo que la segunda MessageBox()
se llama después de descartar el primero MessageBox()
.
No necesitas usar el hWnd
variable en su hilo en absoluto. Estás pasando el diálogo HWND
hacia lpParameter
parámetro de CreateThread()
, por lo que aparecerá en el lpvParam
parámetro de ListenThread()
, p.ej:
DWORD WINAPI ListenThread( LPVOID lpvParam )
{
HWND hWnd = (HWND) lpvParam;
...
return 0;
}