我使用QSharedMemory和qsystemmaphore来组织多个进程之间的事件交换。QSharedMemory存储接收器数量和事件数据。接收者正在qsystemmaphore::acquire()中等待。发送方通过qsystemmaphore::release([接收方数量])通知他们。
除了在共享内存中引入“real”和“fake”标志以及在终止进程中随后生成“fake”事件之外,是否有任何方法可以优雅地终止接收器进程?

最佳答案

QThread::terminate()可以在每个平台上工作,不管线程当前在做什么。当然,当您终止了应用程序中的任何线程时,唯一可以安全地做的另一件事是调用abort:此时进程通常处于中断状态。打电话给abort()后,不要做任何其他事情。因为它是如此具有破坏性,您最好放弃调用QThread::terminate并直接中止。
您的问题的措辞就像您计划在调用terminate之后继续使用应用程序一样。你一定不能!
唉,如果你只想让一个线程退出,而这个信号量是一个同步原语,那么你可以通过设置一个标志并释放这个信号量来轻松地做到这一点。下面是一个有点做作的示例,因为您通常不会那样使用线程池:这只是为了使代码更短。

// https://github.com/KubaO/stackoverflown/tree/master/questions/semaphore-quit-40488523
#include <QtCore>

class Worker : public QRunnable {
    static const QString m_key;
    static QAtomicInteger<bool> m_abort;
    void run() override {
        QSystemSemaphore sem{m_key};
        qDebug() << "working";
        while (true) {
            sem.acquire();
            if (m_abort.load()) {
                sem.release();
                qDebug() << "aborting";
                return;
            }
            sem.release();
        }
    }
public:
    static void acquire(int n = 1) {
        QSystemSemaphore sem{m_key};
        while (n--)
            sem.acquire();
    }
    static void release(int n = 1) {
        QSystemSemaphore{m_key}.release(n);
    }
    static void quit(int n) {
        m_abort.store(true);
        release(n);
    }
};
const QString Worker::m_key = QStringLiteral("semaphore-quit-40488523");
QAtomicInteger<bool> Worker::m_abort = false;

int main()
{
    QThreadPool pool;
    QVarLengthArray<Worker, 20> workers{20};
    for (auto & worker : workers) {
        worker.setAutoDelete(false);
        pool.start(&worker);
    }
    Worker::release(workers.size()); // get some workers churning
    QThread::sleep(5);
    Worker::acquire(workers.size()); // pause all the workers
    Worker::quit(workers.size());
    // The thread pool destructor will wait for all workers to quit.
}

07-24 12:39