La variable externa no está disponible para hustar hasta que se realiza la llamada de bloqueo ...

StackOverflow https://stackoverflow.com/questions/8362999

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 ?

¿Fue útil?

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;  
}  
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top