Win32 CreateWindow() 호출이 하위 스레드에서 중단됩니까?
-
20-09-2019 - |
문제
저는 OpenGL용 이식성 레이어 작업 중입니다(Linux 및 Windows용 glX 및 wgl 항목 추상화).어쨌든 Window를 생성하는 방법이 있습니다.부모를 전달하지 않으면 프레임이 있는 실제 창이 나타납니다.부모를 전달하면 테두리도 없고 프레임도 없는 창이 나타납니다.
1개의 스레드에서 모든 작업을 수행하는 한 이것은 잘 작동합니다.다른 스레드가 하위 창을 만들려고 시도하자마자 win32 호출 "CreateWindow()"에서 앱 교착 상태가 발생합니다.어떤 아이디어가 있나요?
해결책
이것은 실제 대답은 아니지만, 많은 사람들이 Win32가 부모보다 다른 실로 자녀를 창출하는 것을 금지한다고 믿는 것처럼 보이기 때문에, 나는 그 반대의 시위를 게시해야한다고 생각합니다.
아래 코드는 다른 사람에 속하는 부모의 자녀 창의 생성을 보여줍니다. 프로세스. 창 핸들 값을 명령 줄 매개 변수로 받아들이고 해당 부모의 자식 창을 만듭니다.
// t.cpp
#include <windows.h>
#include <stdio.h>
#define CLASS_NAME L"fykshfksdafhafgsakr452"
static LRESULT CALLBACK WindowProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam )
{
switch ( msg )
{
case WM_DESTROY:
PostQuitMessage(0);
break;
case WM_PAINT:
{
PAINTSTRUCT ps;
BeginPaint(hwnd, &ps);
EndPaint(hwnd, &ps);
break;
}
}
return DefWindowProc(hwnd, msg, wParam, lParam);
}
int main( int argc, char* argv[] )
{
HWND parent = (argc >= 2) ? (HWND)strtoul(argv[1], 0, 0) : (HWND)0;
printf("parent: 0x%x\n", parent);
WNDCLASS wc = {};
wc.lpfnWndProc = WindowProc;
wc.hInstance = (HINSTANCE)GetModuleHandle(NULL);
wc.lpszClassName = CLASS_NAME;
wc.hbrBackground = (HBRUSH)(COLOR_ACTIVECAPTION + 1);
if ( !RegisterClass(&wc) )
{
printf("%d: error %d\n", __LINE__, GetLastError());
return 0;
}
const DWORD style = WS_CHILD | WS_VISIBLE;
HWND hwnd = CreateWindow(CLASS_NAME, L"Test", style, 50, 50, 100, 100,
parent, 0, wc.hInstance, 0);
if ( !hwnd )
{
printf("%d: error %d\n", __LINE__, GetLastError());
return 0;
}
MSG msg;
while ( GetMessage(&msg, 0, 0, 0) )
DispatchMessage(&msg);
return 0;
}
다음 명령으로 이것을 컴파일합니다 (MSVC 명령 줄 환경 사용) :
cl /EHsc /DUNICODE /D_UNICODE t.cpp user32.lib
그런 다음 Spy ++ 또는 기타 도구를 사용하여 모든 창의 핸들 값 (예 : 메모장 또는이 사이트를보고있는 브라우저)을 얻습니다. 0x00001234라고 가정 해 봅시다. 그런 다음 컴파일 된 샘플을 사용하여 실행하십시오 t.exe 0x1234
. Ctrl-C를 사용하여 T.exe를 종료하거나 콘솔 창을 닫습니다.
다른 팁
자식 창이 생성되면 SendMessage
. 그러나 그 점에 유의하십시오 SendMessage
스레드 경계를 가로 질러 스레드와 달리 PostMessage
. 부모 창의 실이 자식 실을 기다리고 있고 자식 스레드가 부모가 해당 스레드에있는 창을 만들려고한다면 교착 상태입니다.
일반적으로, 나는 실을 가로 질러 어린이 부모 관계를 만드는 것이 좋은 생각이라고 생각하지 않습니다. 교착 상태를 매우 쉽게 만들 수 있습니다.
여기에는 다른 스레드에 자녀와 부모의 창문을 갖지 않아야한다고 말하고 오히려 작동하지 않을 것이라고 강조한 답변이 여기에 있습니다.
그렇다면 Windows는 CreateWindow를 호출하려고 할 때 약간의 보호 조치를 취하고 단순히 실패합니다. 이제 주요 문제를 일으킬 수있는 스레드 커플 링 문제가 있지만, 이러한 제약 조건으로는 지원되는 시나리오입니다.
이것은 흥미로운 질문입니다.많은 구식 win32 사용자들이 나에게 이 작업을 수행할 수 없다고 말했습니다.이를 조사하면서 다음 포럼을 발견했습니다. 문자 보내().내 현재 이론은 CreateWindowEx()가 존재 권한을 요청하기 위해(또는 적어도 그 존재를 알리기 위해) 부모 창에 메시지(SendMessage()를 통해 차단)를 보내야 한다는 것입니다.어쨌든 상위 스레드가 이러한 메시지를 자유롭게 처리할 수 있는 한 모든 것이 작동합니다...
창은 스레드를 생성하는 스레드에 묶여 있습니다 (특히 스레드의 메시지 대기열에). 부모 창은 자식 창과 다른 스레드에 상주 할 수 없습니다.