0

免責事項:マルチスレッドに関しては、私はやや初心者です。私はオンラインで何かを読んだり、いくつかの簡単なマルチスレッドの例を実行したりしました。

あるスレッドで描画し、別のスレッドで Win32 メッセージを処理する Win32 アプリがあります。ただし、ウィンドウが作成されてスレッドが開始されると、ハングします。WaitForMultipleObjects()と関係があるかもしれないという予感がありますが、それを正しくする方法がわかりません。なぜこれが起こっているのか誰にも分かりますか?スレッドを一時停止して再開する必要がありますか?

これが私のコードです:

WinAPI:

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int nCmdShow)
{
    /* initialization blah blah */

    zgE->startThreads(); // <--- starts the 2 threads

    WaitForMultipleObjects(zgE->getThreadsNo(), zgE->getThreads(), TRUE, INFINITE);
    return TRUE;
}

これは私がスレッドを開始する方法です:

void zgEngine::startThreads()
{
    /* allocation and stuff, blah blah blah */

    m_arrThreads[m_nThreads++] = CreateThread(NULL, 0, &zgEngine::handleMsg, (void*)this, NULL, NULL);
    m_arrThreads[m_nThreads++] = CreateThread(NULL, 0, &zgEngine::drawObjects, (void*)this, NULL, NULL);

    assert(m_nThreads <= THREADS_NO);
}

メッセージを描画して処理する 2 つの関数は非常に単純です。それぞれの while ループ。

// draw function
DWORD WINAPI zgEngine::drawObjects(LPVOID lpParam)
{    
    while (true)
    {
        /* draw stuff - valid code that if called outside this function
           works as intended  */
    }

    return TRUE;
}

// message handler function
DWORD WINAPI zgEngine::handleMsg(LPVOID lpParam)
{
    MSG msg;
    while (true)
    {
        if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
        {
            // Process the message
            if (msg.message == WM_QUIT)
                break;

            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    }

    return TRUE;
}

スレッドを使用せず、drawObjects() の "while (true)" を削除し、コードを残す (1 回だけ実行する) 場合は、下の例のように、handleMsg() を呼び出さずに WinMain を作成します。魅力のように機能します。

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int nCmdShow)
{
    /* initialization blah blah */

    MSG msg;
    while (true)
    {
        if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
        {
            // Process the message
            if (msg.message == WM_QUIT)
                break;

            TranslateMessage(&msg);
            DispatchMessage(&msg);
        } else {
             zgEngine::DrawObjects(zgE);
        } 
    }
    return TRUE;
}

後で編集:私が見たものから、PeekMessage() は常に 0 を返します:(

4

1 に答える 1

2

PeekMessageMicrosoft の Web サイトからの引用:

メッセージを取得するウィンドウへのハンドル。ウィンドウは現在のスレッドに属している必要があります。

hWnd が NULL の場合、PeekMessage は、現在のスレッドに属するウィンドウのメッセージと、現在のスレッドのメッセージ キューにある hwnd 値が NULL のメッセージを取得します (MSG 構造体を参照してください)。したがって、hWnd が NULL の場合、ウィンドウ メッセージとスレッド メッセージの両方が処理されます。

hWnd が -1 の場合、PeekMessage は、hwnd 値が NULL である現在のスレッドのメッセージ キューのメッセージ、つまり、PostMessage (hWnd パラメーターが NULL の場合) または PostThreadMessage によって投稿されたスレッド メッセージのみを取得します。

スレッドには「現在のウィンドウ」がなく、「現在のスレッド メッセージ キュー」は、Windows が実際にデフォルト スレッドとしてメッセージを投稿するものではないと思われます。あなたのアプローチには他の問題がある可能性が十分にあるため、これは単なる仮定です。しかし、これが問題の主な部分だと思います。

于 2013-07-16T13:10:18.600 に答える