Multithreading 具有执行顺序的非阻塞可重入调度队列

Multithreading 具有执行顺序的非阻塞可重入调度队列,multithreading,c++-cx,task-queue,Multithreading,C++ Cx,Task Queue,我正在尝试实现自己的调度队列,以便按照任务添加到队列中的相同顺序来调度任务。这样做的动机是由于缺乏对Windows运行时组件调度队列的C++/CX支持。是我一直在考虑的文件。我知道这与问题有关,但我还没有用C++/CX解决它。鉴于此,我尝试了几种解决这个问题的方法 根据我在网上找到的几个例子和文档,我尝试使用信号量来解决这个问题。为此,我创建了一个包含多个属性的DispatchQueue类: namespace Threading { ref class DispatchQueue

我正在尝试实现自己的调度队列,以便按照任务添加到队列中的相同顺序来调度任务。这样做的动机是由于缺乏对Windows运行时组件调度队列的C++/CX支持。是我一直在考虑的文件。我知道这与问题有关,但我还没有用C++/CX解决它。鉴于此,我尝试了几种解决这个问题的方法

根据我在网上找到的几个例子和文档,我尝试使用信号量来解决这个问题。为此,我创建了一个包含多个属性的
DispatchQueue
类:

namespace Threading
{
    ref class DispatchQueue
    {

    private:
        typedef IMap<String^, DispatchQueue^> MapType;
        typedef std::function<void()> TaskType;
        typedef std::queue<TaskType> QueueType;

    internal:

        static DispatchQueue^ Get();

        void Add(TaskType task);

    private:
        TaskType DequeueTask();
        void Runner();

        QueueType & GetQueue();
        const QueueType & GetQueue() const;

    private:
        QueueType _queue;
        std::mutex _queue_mux;
        std::mutex _add_mux;
        HANDLE _emptySemaphore;
        HANDLE _fullSemaphore;
    };
}
这是我的制作人:

void Threading::DispatchQueue::Add(TaskType task)
{
    // Prevent different threads from entering this method
    // Disregard the mutex being static
    static std::mutex mux;
    std::lock_guard<std::mutex> lock(mux);

    WaitForSingleObject(_emptySemaphore, INFINITE);
    {
        // Prevent concorrent access to the queue
        std::lock_guard<std::mutex> lock(_queue_mux);
        GetQueue().push(task);
    }
    ReleaseSemaphore(_fullSemaphore, 1, NULL);
}
我还尝试在释放信号量后分派任务(
task();
),但也不起作用。同样值得注意的是,
Runner
(使用者)在初始化点启动:

    create_task([dispatchQueue]() {

        dispatchQueue->Runner();
    });
这种方法的问题是调用
task()
还可能生成新任务(
任务类型
),但这似乎不可重入。因此,实现阻塞。发生锁定是因为任务在没有释放信号量的情况下进入
Add
方法

我反复尝试了这个制作人:

void Threading::DispatchQueue::Add(TaskType task)
{
    create_task([this, task]()
    {
        WaitForSingleObject(_emptySemaphore, INFINITE);
        {
            std::lock_guard<std::mutex> lock(_queue_mux);
            GetQueue().push(task);
        }
        ReleaseSemaphore(_fullSemaphore, 1, NULL);

    }).wait();   // Notice we're waiting
}
void Threading::DispatchQueue::Add(TaskType任务)
{
创建_任务([此,任务]()
{
WaitForSingleObject(_emptySemaphore,无限);
{
std::锁\保护锁(\队列\多路复用器);
GetQueue().push(任务);
}
释放信号量(_fullSemaphore,1,NULL);
}).wait();//注意我们正在等待
}
wait()
背后的动机是确保任务以正确的顺序插入队列。这确实有效,但如果从UI线程调用此方法,则会崩溃。这不是一个选择。此外,不等待也不是一个选项,因为任务没有按正确的顺序调度

我也试过,这也会阻碍


简言之,我需要一个调度队列,它尊重插入顺序,而不阻塞生产线程,因为它可以是主线程。这些方法或您推荐的任何其他方法都有解决方案吗?

大量文本,问题陈述基本上归结为“它不起作用”。还有,我不明白的是,创建最大计数为1的信号量的基本原理是什么?那么为什么不使用互斥锁呢?我在好几个地方(例如)读到,使用互斥锁无法解决这个问题。不过,我一次只想分派一个任务。互斥和二进制信号量有不同的用途。然而,在使用二进制信号量的方式中,可以使用互斥来替换它,并公开完全相同的行为。我只是想知道是否还有更多,不是真的。这段代码已经迭代了很多次。根据链接中的范例,我们从满信号量和空信号量开始。
    create_task([dispatchQueue]() {

        dispatchQueue->Runner();
    });
void Threading::DispatchQueue::Add(TaskType task)
{
    create_task([this, task]()
    {
        WaitForSingleObject(_emptySemaphore, INFINITE);
        {
            std::lock_guard<std::mutex> lock(_queue_mux);
            GetQueue().push(task);
        }
        ReleaseSemaphore(_fullSemaphore, 1, NULL);

    }).wait();   // Notice we're waiting
}