ブロッキングコールが作成されるまで、外部変数はスレッドできません…
-
27-10-2019 - |
質問
2つのコードファイルがあります。1つは私のコードファイルが含まれています WinMain()
関数、およびメインダイアログウィンドウに関連するすべての機能。もう1つには、私のプログラムに関連するスレッドコールバックと変数関数が含まれています。私は定義しました 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
?
解決
WM_INITDIALOG
メッセージが発生します 前 CreateDialog
返品と hWnd
まで設定されていません CreateDialog
戻り値。したがって、createdialogが戻ってきてグローバルを設定する前に、スレッドは実行を開始します hWnd
変数。
したがって、スレッドの作成をから移動することでこれを修正できます WM_INITDIALOG
の帰還直後のメッセージ CreateDialog
.
しかし、あなたはグローバルを必要としないので、あなたはそれをする必要はありません hWnd
変数。スレッド開始手順のパラメーターとしてダイアログウィンドウハンドルを既に渡しています。だから、lpvparamをanにキャストしてください 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;
}
他のヒント
WM_INITDIALOG
メッセージが発行されます WndProc()
内側から CreateDialog()
それ自体ではなく DispatchMessage()
. 。これは、と同じように述べられています CreateDialog()
ドキュメンテーション. 。君の hWnd
変数は後まで割り当てられません CreateDialog()
出口。スレッドが以前に実行され始めた場合 CreateDialog()
出口(タスクのスケジューリングに応じて、それは保証ではありません)、あなたの最初の MessageBox()
呼び出されます。一方 MessageBox()
が走っています、 CreateDialog()
変数を終了して割り当てる時間があるので、2番目の変数が MessageBox()
あなたが最初のものを却下した後に呼び出されます MessageBox()
.
使用する必要はありません hWnd
スレッドの変数。あなたはダイアログを渡しています HWND
に lpParameter
のパラメーター CreateThread()
, 、したがって、に表示されます lpvParam
のパラメーター ListenThread()
, 、例:
DWORD WINAPI ListenThread( LPVOID lpvParam )
{
HWND hWnd = (HWND) lpvParam;
...
return 0;
}