La variabile esterna non è disponibile per il thread fino a quando non viene effettuata la chiamata di blocco ...

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

Domanda

Ho due file di codice, uno contiene il mio WinMain() funzione e tutte le funzioni relative alla mia finestra di dialogo principale. L'altro contiene un callback thread e funzioni variabili relative al mio programma. Ho definito HWND hWnd = NULL come variabile globale in maindlg.cpp e definita extern HWND hWnd in altri.cpp (che contiene il callback del thread). Il thread viene creato quando il WM_INITDIALOG Il messaggio viene inviato alla finestra. All'interno del callback del thread, il hWnd La variabile è null fino a quando non viene eseguita una lunga operazione, quindi dopo che diventa disponibile.

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;
}

Altro.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;
}

Entrambe le caselle di messaggi nel file ListenThread Il callback viene visualizzato al momento dell'avvio dell'applicazione. Qualcuno può dirmi perché sta accadendo? C'è qualcosa che posso fare per risolvere questo problema oltre a farlo while( hWnd == NULL ); All'inizio del mio ListenThread ?

È stato utile?

Soluzione

Il WM_INITDIALOG si verifica il messaggio prima CreateDialog ritorna e hWnd non è impostato fino a quando CreateDialog ritorna. Quindi il thread inizia in esecuzione prima che CreateAlog ritorni e imposta il globale hWnd variabile.

Quindi potresti risolverlo spostando la creazione del tuo thread da WM_INITDIALOG messaggio a subito dopo il ritorno di CreateDialog.

Ma non è necessario farlo perché il codice non richiede il globale hWnd variabile. Stai già passando la maniglia della finestra di dialogo come parametro nella procedura di avvio del thread. Quindi basta lanciare LPVParam su un HWND e usalo. Ciò ti permetterà di sbarazzarti della tua variabile globale, che è una cattiva pratica da usare.

Altro.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;
}

Altri suggerimenti

Il WM_INITDIALOG il messaggio viene emesso WndProc() dall'interno di CreateDialog() se stesso, non da DispatchMessage(). Questo è indicato tanto in CreateDialog() documentazione. Tuo hWnd La variabile non è assegnata fino a dopo CreateDialog() uscite. Se il thread inizia a funzionare prima CreateDialog() Esci (a seconda della pianificazione delle attività, non è una garanzia), il tuo primo MessageBox() viene chiamato. Mentre il MessageBox() è in esecuzione, CreateDialog() ha il tempo di uscire e assegnare la variabile, motivo per cui il secondo MessageBox() Viene chiamato dopo aver respinto il primo MessageBox().

Non è necessario usare il hWnd variabile nel tuo thread. Stai passando la finestra di dialogo HWND al lpParameter parametro di CreateThread(), quindi apparirà in lpvParam parametro di ListenThread(), per esempio:

DWORD WINAPI ListenThread( LPVOID lpvParam )  
{  
    HWND hWnd = (HWND) lpvParam;  
    ...
    return 0;  
}  
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top