2011-12-02 2 views
0

У меня есть два файла кода, один содержит мою функцию WinMain() и все функции, связанные с моим основным диалоговым окном. Другая содержит функции обратного вызова потока и переменные, связанные с моей программой. Я определил HWND hWnd = NULL как глобальную переменную в MainDlg.cpp и определил extern HWND hWnd в файле Other.cpp (который содержит обратный вызов потока). Поток создается, когда сообщение WM_INITDIALOG отправляется в окно. Внутри обратного вызова потока переменная hWnd имеет значение null, пока не будет выполнена длительная операция, после чего она станет доступной.Внешняя переменная недоступна для потока до тех пор, пока не будет выполнен блокирующий вызов ...

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

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

Оба окна сообщений в ListenThread обратного вызова отображаются при запуске приложения. Может кто-нибудь, пожалуйста, скажите мне, почему это происходит? Есть ли что-то, что я могу сделать, чтобы исправить это, кроме while(hWnd == NULL); в начале моего ListenThread?

ответ

3

WM_INITDIALOG сообщение происходит доCreateDialog возвращается и hWnd не не установлен до CreateDialog возвращается. Таким образом, поток запускается до того, как возвращается CreateDialog, и задает глобальную переменную hWnd.

Таким образом, вы можете исправить это, перемещая создание потока из сообщения WM_INITDIALOG сразу после возврата CreateDialog.

Но вам не нужно это делать, потому что вам не требуется глобальная переменная hWnd. Вы уже передаете дескриптор окна диалога в качестве параметра в процедуру запуска потока. Так что просто бросьте lpvParam на HWND и используйте это. Это позволит вам избавиться от вашей глобальной переменной, что является плохой практикой в ​​использовании.

Other.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; 
} 
+0

Как я ехал домой с работы, я понял, что это то, что это было.Передача 'hWndDlg' в параметр потока' lpvParam' на самом деле не должна была быть в этом вопросе. Это было с самого начала разработки кода, прежде чем я обнаружил, что мне нужно больше «внешних» переменных и изменить его на «extern». Я просто забыл удалить его. –

1

WM_INITDIALOG сообщение выдается WndProc() внутри самого CreateDialog(), а не DispatchMessage(). Это указано так же в CreateDialog()documentation. Ваша переменная hWnd не назначается после завершения CreateDialog() выходов. Если ваш поток начинает работать до выхода CreateDialog() (в зависимости от планирования задач, это не гарантия), вызывается ваш первый MessageBox(). Пока работает MessageBox(), CreateDialog() имеет время выхода и назначает переменную, поэтому вторая MessageBox() вызывается после того, как вы уволили первый MessageBox().

Вам необязательно использовать переменную hWnd в вашей теме. Вы передаете диалоговое HWND параметру CreateThread()lpParameter, поэтому он будет отображаться в параметре ListenThread()lpvParam, например:

DWORD WINAPI ListenThread(LPVOID lpvParam) 
{ 
    HWND hWnd = (HWND) lpvParam; 
    ... 
    return 0; 
} 

 Смежные вопросы

  • Нет связанных вопросов^_^