> ## Documentation Index
> Fetch the complete documentation index at: https://devdocs.xbox.com/llms.txt
> Use this file to discover all available pages before exploring further.

# XTaskQueueTerminate

> XTaskQueueTerminate

# XTaskQueueTerminate

保留中のすべての項目をキャンセルし、新しい項目がキューに登録されないようにすることで、タスク キューを終了します。

## 構文

```cpp theme={null}
HRESULT XTaskQueueTerminate(  
         XTaskQueueHandle queue,  
         bool wait,  
         void* callbackContext,  
         XTaskQueueTerminatedCallback* callback  
)  
```

### パラメーター

*queue*   \_In\_\
Type: XTaskQueueHandle

終了するキューです。

*wait*   \_In\_\
Type: bool

終了処理の完了を待機するには true を指定します。

*callbackContext*   \_In\_opt\_\
Type: void\*

コールバックに渡す省略可能なコンテキスト ポインターです。

*callback*   \_In\_opt\_\
Type: XTaskQueueTerminatedCallback\*

キューの終了時に呼び出される省略可能なコールバックです。

### 戻り値

Type: HRESULT

HRESULT の成功またはエラー コード。

## 解説

<Note>この関数は、時間依存スレッドで呼び出しても安全ではありません。詳細については、[Time-sensitive threads](https://learn.microsoft.com/gaming/gdk/docs/gdk-dev/console-dev/overviews/threads/time-sensitive-threads) を参照してください。</Note>

[XTaskQueueCloseHandle](/reference/system/xtaskqueue/functions/xtaskqueueclosehandle) は、タスク キュー オブジェクトの内部参照カウントを単純にデクリメントするだけです。まだキューにコールバックが残っている場合、それらのコールバックはキュー オブジェクトに対する参照を保持しており、引き続き呼び出される可能性があります。これはアプリケーションのシャットダウン時に問題となる可能性があります。アプリケーションをシャットダウンする際は、クリーンアップ後に意図しないコールバックが実行されないようにする必要があります。XTaskQueue は、キューの制御された終了を実行するために **XTaskQueueTerminate** API を提供します。

タスク キューを終了すると、次の処理が実行されます:

1. 両方のポートのすべてのコールバックが、*canceled* パラメーターが true に設定された状態で呼び出されます。
2. ワーク ポートで保留中のすべてのコールバックがディスパッチされます。ワーク ポートに新しいコールバックを送信すると E\_ABORT で失敗します。
3. 完了ポートで保留中のすべてのコールバックがディスパッチされます。完了ポートに新しいコールバックを送信すると E\_ABORT で失敗します。

このプロセスが完了すると、wait が true の場合は **XTaskQueueTerminate** が戻ります。wait が false の場合、終了は非同期に行われます。終了コールバックを指定した場合、終了処理の最後に完了スレッドから呼び出されます。

<Note />

* **XTaskQueueTerminate** はキュー ハンドルを閉じません。終了処理後も [XTaskQueueCloseHandle](/reference/system/xtaskqueue/functions/xtaskqueueclosehandle) を呼び出す必要があります。
* [XTaskQueueDispatch](/reference/system/xtaskqueue/functions/xtaskqueuedispatch) を呼び出してキュー コールバックを処理しているスレッドで **XTaskQueueTerminate** を呼び出す場合は、wait パラメーターに true を渡さないでください。渡すとデッドロックが発生する可能性があります。

次の例では、以前に作成したタスク キューを終了する方法を示します。

<Note>**SubmitCallback** は、[XTaskQueueSubmitCallback](/reference/system/xtaskqueue/functions/xtaskqueuesubmitcallback) 関数のコード例で定義されているヘルパー関数です。</Note>

```cpp theme={null}
void CreatingTaskQueue()
{
    XTaskQueueHandle queue;
    HRESULT hr = XTaskQueueCreate(XTaskQueueDispatchMode::ThreadPool, XTaskQueueDispatchMode::ThreadPool, &queue);
    if (FAILED(hr))
    {
        printf("Creating queue failed: 0x%x\r\n", hr);
        return;
    }

    SubmitCallbacks(queue);

    // Wait a while for the callbacks to run
    Sleep(1000);

    XTaskQueueTerminate(queue, true, nullptr, nullptr);
}
```

タスク キューは UI スレッドと統合できます。通常は、完了ポートにキューされたコールバックを UI スレッドで実行させたいでしょう。この例では、作業にはスレッド プールを使用しますが、完了ポートのコールバックは Win32 のウィンドウ プロシージャーに統合します。また、他のスレッド モデルと統合する場合の、タスク キューの正しい終了方法も示しています。

```cpp theme={null}
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 will do work on the thread pool, but completion
        // callbacks should be manual so 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 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 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);
    }
}
```

## 要件

**ヘッダー:** XTaskQueue.h

**ライブラリ:** xgameruntime.lib

**サポートされているプラットフォーム:** Windows、XBOX One 本体、XBOX Series 本体

## 概念ドキュメント

* [タスク キューのクリーンアップ](/build/core-features/common/async/async-libraries/async-library-xtaskqueue-example-cleanup-task-queue)
* [Time-sensitive threads](https://learn.microsoft.com/gaming/gdk/docs/gdk-dev/console-dev/overviews/threads/time-sensitive-threads)

## 関連項目

[XTaskQueue members](/reference/system/xtaskqueue/xtaskqueue_members)\
[非同期プログラミング モデル](/build/core-features/common/async/async-programming-model)\
[非同期タスク キューの設計](/build/core-features/common/async/async-task-queue-design)


## Related topics

- [XTaskQueueTerminatedCallback](/ja-jp/reference/system/xtaskqueue/functions/xtaskqueueterminatedcallback.md)
- [XTaskQueueCloseHandle](/ja-jp/reference/system/xtaskqueue/functions/xtaskqueueclosehandle.md)
- [XTaskQueueCallback](/ja-jp/reference/system/xtaskqueue/functions/xtaskqueuecallback.md)
- [XTaskQueue](/ja-jp/reference/system/xtaskqueue/xtaskqueue_members.md)
- [タスク キューのクリーンアップ例](/ja-jp/build/core-features/common/async/async-libraries/async-library-xtaskqueue-example-cleanup-task-queue.md)
