> ## 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.

# How to: Using events to control manual queue dispatching

> How to: Using events to control manual queue dispatching

## Example

A game might want to share threads that it uses for the task queue with other work in the game. The following example shows how to use a task queue to signal a condition variable when it has items to dispatch.

```c++ theme={null}
// We use condition variables to signal when there's something for us  
// in the queue and a bool to signal when we want the whole thing to close.  
// Keep all this in a struct for convenient access.  
struct QueueControl  
{  
    std::condition_variable workActivity;  
    std::mutex workMutex;  
    std::condition_variable completionActivity;  
    std::mutex completionMutex;  
    bool terminate = false;  
} queueControl;  
  
void CALLBACK TaskQueueNewItemSubmitted(  
    void* context, XTaskQueueHandle, XTaskQueuePort port)  
{  
    // A new callback has been submitted. Notify the correct condition variable.  
    QueueControl* queueControl = static_cast<QueueControl*>(context);  
    switch (port)  
    {  
    case XTaskQueuePort::Work:  
        queueControl->workActivity.notify_all();  
        break;  
  
    case XTaskQueuePort::Completion:  
        queueControl->completionActivity.notify_all();  
        break;  
    }  
}  
  
void CreatingTaskQueueWithManualSignaling()  
{  
    // Create a manual task queue.  
    XTaskQueueHandle queue;  
    HRESULT hr = XTaskQueueCreate(  
        XTaskQueueDispatchMode::Manual,  
        XTaskQueueDispatchMode::Manual,  
        &queue);  
  
    if (FAILED(hr))  
    {  
        printf("Creating queue failed: 0x%x\r\n", hr);  
        return;  
    }  
  
    // Listen to callback-submitted notifications to signal  
    // our condition variable.  
    XTaskQueueRegistrationToken token;  
    hr = XTaskQueueRegisterMonitor(  
        queue, &queueControl,  
        TaskQueueNewItemSubmitted, &token);  
  
    std::thread workThread([&]()  
    {  
        std::unique_lock<std::mutex> lock(queueControl.workMutex);  
        while (!queueControl.terminate)  
        {  
            queueControl.workActivity.wait(lock);  
            XTaskQueueDispatch(queue, XTaskQueuePort::Work, 0);  
        }  
    });  
  
    std::thread completionThread([&]()  
    {  
        std::unique_lock<std::mutex> lock(queueControl.completionMutex);  
        while (!queueControl.terminate)  
        {  
            queueControl.completionActivity.wait(lock);  
            XTaskQueueDispatch(queue, XTaskQueuePort::Completion, 0);  
        }  
    });  
  
    SubmitCallbacks(queue);  
  
    // Wait a while for the callbacks to run.  
    Sleep(1000);  
  
    XTaskQueueTerminate(queue, true, nullptr, nullptr);  
  
    queueControl.terminate = true; 
    queueControl.workActivity.notify_all(); 
    queueControl.completionActivity.notify_all();  
  
    workThread.join();  
    completionThread.join();  
}  
```

## See also

[Designing the task queue](/build/core-features/common/async/async-task-queue-design)


## Related topics

- [XTaskQueueMonitorCallback](/reference/system/xtaskqueue/functions/xtaskqueuemonitorcallback.md)
- [Async task queue design](/build/core-features/common/async/async-task-queue-design.md)
- [How to: Using the process task queue](/build/core-features/common/async/async-task-queue-design-howto/using-process-task-queue.md)
- [How to: Creating a manual task queue](/build/core-features/common/async/async-task-queue-design-howto/creating-manual-task-queue.md)
- [Asynchronous Programming Model](/build/core-features/common/async/async-programming-model.md)
