在阻塞调用之前,外部变量对线程不可用
external variable is not available to thread until blocking call is made...
我有两个代码文件,一个包含我的WinMain()
函数,以及与我的主对话框窗口相关的所有函数。另一个包含线程回调和与我的程序相关的变量函数。我在maindg .cpp中定义了HWND hWnd = NULL
作为全局变量,并在Other.cpp中定义了extern HWND hWnd
(其中包含线程回调)。当WM_INITDIALOG
消息被发送到窗口时创建线程。在线程回调中,hWnd
变量在执行long操作之前为空,之后变为可用。
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
回调中的两个消息框都会显示。谁能告诉我为什么会这样?除了在ListenThread
开始时做while( hWnd == NULL );
之外,我还可以做些什么来解决这个问题吗?
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;
}
WM_INITDIALOG
消息是从CreateDialog()
内部发出给WndProc()
的,而不是由DispatchMessage()
发出的。这在CreateDialog()
文档中有详细说明。直到CreateDialog()
退出后才分配hWnd
变量。如果您的线程在CreateDialog()
退出之前开始运行(取决于任务调度,这并不能保证),您的第一个MessageBox()
将被调用。当MessageBox()
运行时,CreateDialog()
有时间退出并分配变量,这就是为什么在您解散第一个MessageBox()
之后调用第二个MessageBox()
的原因。
hWnd
变量。您将对话框HWND
传递给CreateThread()
的lpParameter
参数,因此它将出现在ListenThread()
的lpvParam
参数中,例如:
DWORD WINAPI ListenThread( LPVOID lpvParam )
{
HWND hWnd = (HWND) lpvParam;
...
return 0;
}
- C++Boost Asio Pool线程,带有lambda函数和传递引用变量
- 类与私有变量的其他类之间的线程安全性
- 全局变量 多读取器 一个写入器多线程安全?
- 静态 constexpr 类成员变量对多线程读取是否安全?
- 成员变量在多线程 C++ 时自行更改
- C++线程安全:如果只有一个线程可以写入非原子变量,但多个线程从中读取. 会遇到问题吗?
- 多个线程可以安全地同时将相同的值写入同一变量吗?
- C++11:具有互斥锁的线程看到原子变量的值发生变化,尽管这是唯一可以改变它的代码
- C++线程不检测全局变量更改
- 为什么 beginthreadex 线程参数变量在父线程中没有更新
- C++多线程程序:变量定义为类成员的隔离错误
- std::线程不是全局变量,但在到达创建它的函数的末尾时不会超出范围?
- 对全局变量的多线程访问:我应该使用互斥锁吗?
- 子线程中的条件变量等待停止主线程中的执行
- 是局部unordered_map变量线程在C 中安全的线程
- 如何使类静态变量线程安全
- 命名空间中的全局变量 - 线程中的值不同
- 静态变量与堆栈变量:线程安全与堆栈大小
- 共享提升::shared_ptr<>变量线程安全吗?
- 在析构函数中pthead_join()类成员变量线程是否明智?