Eine externe Variable ist erst verfügbar, wenn der Blockierungsanruf getätigt wird…
-
27-10-2019 - |
Frage
Ich habe zwei Codedateien, einer enthält meine WinMain()
Funktion und alle Funktionen, die sich auf mein Hauptdialogfenster beziehen. Der andere enthält einen Thread -Rückruf und eine variable Funktionen, die sich auf mein Programm beziehen. Ich habe definiert HWND hWnd = NULL
als globale Variable in MainDLg.cpp und definiert extern HWND hWnd
in anderen.cpp (der den Thread -Rückruf enthält). Der Thread wird erstellt, wenn der WM_INITDIALOG
Nachricht wird an das Fenster gesendet. Innerhalb des Thread -Rückrufs, das hWnd
Variable ist null, bis der lange Betrieb durchgeführt wird, und danach wird sie verfügbar.
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;
}
Beide Nachrichtenfelder in der ListenThread
Rückrufe werden angezeigt, wenn die Anwendung gestartet wird. Kann mir bitte jemand sagen, warum das passiert? Gibt es etwas, das ich tun kann, um dies zu reparieren, außerdem zu tun, außer zu tun? while( hWnd == NULL );
Zu Beginn meiner ListenThread
?
Lösung
Das WM_INITDIALOG
Nachricht tritt auf Vor CreateDialog
kehrt zurück und hWnd
ist nicht eingestellt, bis CreateDialog
kehrt zurück. Daher beginnt der Thread zu läufen, bevor das CreateDialog zurückkehrt und die globale festlegt hWnd
Variable.
Sie können dies also beheben, indem Sie Ihre Thread -Kreation von der verschieben WM_INITDIALOG
Nachricht an kurz nach der Rückkehr von CreateDialog
.
Sie müssen dies jedoch nicht tun, da Ihr Code das globale nicht benötigt hWnd
Variable. Sie übergeben bereits Ihr Dialog -Fenster -Handle als Parameter an die Thread -Startvorgangsvorgang. Also werfen Sie einfach das LPVParam auf eine HWND
und benutze das. Dadurch können Sie Ihre globale Variable loswerden, was eine schlechte Praxis ist.
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;
}
Andere Tipps
Das WM_INITDIALOG
Nachricht wird an ausgegeben WndProc()
von innen von CreateDialog()
selbst nicht durch DispatchMessage()
. Dies ist genauso viel in der CreateDialog()
Dokumentation. Dein hWnd
Variable wird erst nachher zugewiesen CreateDialog()
Ausgänge. Wenn Ihr Thread vor dem Laufen beginnt, bevor CreateDialog()
beendet (abhängig von der Aufgabenplanung, das ist keine Garantie), Ihre erste MessageBox()
wird angerufen. Während MessageBox()
läuft, CreateDialog()
hat Zeit zum Beenden und Zuweisen der Variablen, weshalb der zweite der zweite ist MessageBox()
wird angerufen, nachdem Sie den ersten entlassen haben MessageBox()
.
Sie müssen die nicht verwenden hWnd
Variable in Ihrem Thread überhaupt. Sie bestehen den Dialog HWND
zum lpParameter
Parameter von CreateThread()
, so wird es in der erscheinen lpvParam
Parameter von ListenThread()
, z.B:
DWORD WINAPI ListenThread( LPVOID lpvParam )
{
HWND hWnd = (HWND) lpvParam;
...
return 0;
}