如何仅使用 win32 API 将主窗口的句柄传递给新线程?



我已经读到我需要将HWND放置在堆上。这是正确的吗?

我需要它从用户输入中读取值。

提前谢谢!

VOID MakeThread(HWND hWnd)
{
HWND* h = new HWND(hWnd);
HANDLE hThread = (HANDLE)_beginthreadex(nullptr, 0, WorkerThread, h, 0, nullptr);
if (hThread != nullptr) {
WaitForSingleObject(hThread, INFINITE);
CloseHandle(hThread);
}
delete h;
}
unsigned int __stdcall WorkerThread(VOID* h)
{
char num[71] = { 0 };
GetDlgItemTextA((*(HWND*)h), 2001, num, 70);
//Get number from edit box 2001
//Do work with the above-mentioned number
return 0;
}

我读到我需要将HWND放置在堆上。这是正确的吗

不是。假设HWND在创建的线程期间保持有效(如果它是应用程序的主窗口,那么这是一个合理的假设(,MakeThread函数在该线程完成之前不会返回(就像您的代码中的情况一样(,那么您可以在对_beginthreadex的调用中将其HWND hWnd参数的地址作为arglist参数。

您不必在堆上创建该窗口句柄的副本。以下是MakeThread函数的简化版本:

VOID MakeThread(HWND hWnd)
{
stringstream stream;
stream << &hWnd << "n" << hWnd;
std::string s = stream.str();
MessageBoxA(hWnd, s.c_str(), "Caller: hWnd?", 0);
HANDLE hThread = (HANDLE)_beginthreadex(nullptr, 0, WorkerThread, &hWnd, 0, nullptr);
if (hThread != nullptr) {
WaitForSingleObject(hThread, INFINITE);
CloseHandle(hThread);
}
}

但是,如果MakeThread函数返回不等待创建的线程完成,则传递的地址将变为无效(在某个时刻(。但是,在这种情况下,您必须对代码进行其他更改,以便跟踪创建的线程句柄。

HWND已经是指针类型(指向全局系统资源(。你可以按原样传递它,根本不需要用new包裹它:

void MakeThread(HWND hWnd)
{
HANDLE hThread = (HANDLE)_beginthreadex(nullptr, 0, WorkerThread, hWnd, 0, nullptr);
if (hThread != nullptr) {
WaitForSingleObject(hThread, INFINITE);
CloseHandle(hThread);
}
}
unsigned int __stdcall WorkerThread(void* h)
{
char num[71] = { 0 };
GetDlgItemTextA((HWND)h, 2001, num, 70);
//Get number from edit box 2001
//Do work with the above-mentioned number
return 0;
}

也就是说,创建一个线程只是为了立即等待它的终止,这完全是对线程的浪费。你也可以直接调用目标函数,最终结果将完全相同,只是没有额外的开销:

void DontMakeThread(HWND hWnd)
{
WorkerThread(hWnd);
}

一旦使用new HWND(hWnd),您的对象将默认分配在堆上,而不是堆栈上。因此,您可以在没有因堆栈展开而丢失对象的风险的情况下共享它。

另一点是启动线程,然后等待完成。作为副作用,您甚至可以使用堆栈分配的数据来传递给线程,因为堆栈在线程退出之前一直在这里(确切地说,是WaitForSingleObject行(。

通常,处理用户输入与堆/堆栈分配无关。你能在那个部分重新表述你的问题吗?还是在这个意思上再提出一个问题?

最新更新