次の方法で共有


方法: Windows メッセージ ループでのタスク キューの使用

タスク キューは Windows メッセージ ループに統合できます。 通常は、コールバックがメッセージ ループと同じスレッド上で実行するためには、完了ポートのキューに入れる必要があります。

次の例では、処理のためにスレッド プールを使用しますが、完了ポート コールバックを Win32 ウィンドウ プロシージャに統合します。 また、この例は、別のスレッド モデルに統合する際に、タスク キューを適切に終了する方法も示します。

  
// Example of using a task queue and Window proc together.  
  
XTaskQueueHandle g_queue; 
XTaskQueueRegistrationToken g_monitorToken;  
  
// Posted when there's a completion callback.  
#define WM_QUEUE_COMPLETION (WM_USER + 1)  
  
struct WorkData  
{  
    HWND hwnd;  
    WCHAR text[80];  
};  
  
void CALLBACK WorkCompletion(void* context, bool cancel)  
{  
    WorkData* data = (WorkData*)context;  
  
    if (!cancel)  
    {  
        SetWindowText(data->hwnd, data->text);  
    }  
  
    delete data;  
}  
  
void CALLBACK BackgroundWork(void* context, bool cancel)  
{  
    if (!cancel)  
    {  
        WorkData* data = new WorkData;  
        data->hwnd = (HWND)context;  
  
        if (GetTimeFormatEx(  
            LOCALE_NAME_USER_DEFAULT, 0, nullptr,  
            nullptr, data->text, 80) == 0)  
        {  
            swprintf_s(data->text, L"Error : %d", GetLastError());  
        }  
  
        // Now, take our formatted string and submit it as a completion callback. 
        XTaskQueueSubmitCallback(  
            g_queue,  
            XTaskQueuePort::Completion,  
            data,  
            WorkCompletion);  
    }  
}  
  
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)  
{  
    HRESULT hr;  
  
    switch (msg)  
    {  
    case WM_CREATE:  
  
        // We'll do work on the thread pool, but completion  
        // callbacks should be manual so that we can integrate them with  
        // the message loop.  
  
        hr = XTaskQueueCreate(  
            XTaskQueueDispatchMode::ThreadPool,  
            XTaskQueueDispatchMode::Manual,  
            &g_queue);  
  
        if (SUCCEEDED(hr))  
        {  
            hr = XTaskQueueRegisterMonitor(g_queue, hwnd,  
                [](void* context, XTaskQueueHandle, XTaskQueuePort port)  
            {  
                // If a new callback was submitted to the completion  
                // port, post a message so that we dispatch it in our message loop.  
                if (port == XTaskQueuePort::Completion)  
                {  
                    HWND hwnd = static_cast<HWND>(context);  
                    PostMessage(hwnd, WM_QUEUE_COMPLETION, 0, 0);  
                }  
            }, &g_monitorToken);  
        }  
  
        if (FAILED(hr))  
        {  
            PostQuitMessage(1);  
            return 0;  
        }  
        break;  
  
    case WM_LBUTTONDOWN:  
        hr = XTaskQueueSubmitCallback(  
            g_queue,  
            XTaskQueuePort::Completion,  
            hwnd,  
            BackgroundWork);  
  
        if (FAILED(hr))  
        {  
            MessageBox(hwnd, L"Failed to submit callback.", L"Error", MB_OK);  
        }  
        break;  
  
    case WM_QUEUE_COMPLETION:  
        XTaskQueueDispatch(g_queue, XTaskQueuePort::Completion, 0);  
        break;  
  
    case WM_CLOSE:  
  
        // Terminate the task queue. When this is done, destroy our window.  
        // The termination callback is queued to the completion  
        // port, so it will already be on the UI thread.  
  
        hr = XTaskQueueTerminate(g_queue, false, hwnd, [](void* context)  
        {  
            HWND hwnd = static_cast<HWND>(context);  
            DestroyWindow(hwnd);  
            XTaskQueueUnregisterMonitor(g_queue, g_monitorToken);  
            XTaskQueueCloseHandle(g_queue);  
        });  
  
        if (SUCCEEDED(hr))  
        {  
            // Prevent DefWndProc from destroying our window because  
            // the termination callback will do it.  
            return 0;  
        }  
        break;  
  
    case WM_DESTROY:  
        PostQuitMessage(0);  
        break;  
  
    }  
  
    return DefWindowProc(hwnd, msg, wParam, lParam);  
}  
  
void TestWndProc()  
{  
    WNDCLASS wndClass;  
    ZeroMemory(&wndClass, sizeof(wndClass));  
    wndClass.lpfnWndProc = WndProc;  
    wndClass.lpszClassName = L"TestClass";  
    wndClass.hInstance = GetModuleHandle(nullptr);  
    wndClass.hbrBackground = GetSysColorBrush(COLOR_WINDOW);  
  
    ATOM c = RegisterClass(&wndClass);  
  
    HWND h = CreateWindow(L"TestClass", L"Window",  
        WS_OVERLAPPEDWINDOW | WS_VISIBLE,  
        10, 10, 300, 100, nullptr, nullptr,  
        GetModuleHandle(nullptr), 0);  
  
    if (!h)  
    {  
        return;  
    }  
  
    MSG m;  
  
    while (GetMessage(&m, nullptr, 0, 0))  
    {  
        TranslateMessage(&m);  
        DispatchMessage(&m);  
    }  
}  

関連項目

タスク キューの設計