Thread pausing/resuming/canceling with Qt
The code you have is unsafe, because pause() and cancelWork() are called from outside the worker's thread, and they use no locking when modifying the worker's members.

In general, prefer to interact with objects in other threads by invoking their slots via queued connections, unless there's a pressing reason to act immediately.  This means you don't need any of the synchronization facilities inside the worker.  This simplifies the coding, and makes it easier to test.

To do that, the worker needs to periodically process events.  I prefer to put this in a function of its own:

bool isCancelled() {
    auto dispatcher = QThread::currentThread()-&gt;eventDispatcher();
    if (!dispatcher) return false;
    dispatcher-&gt;processEvents();
    return m_cancelRequested;
}


In the work method, this can be called every time you want to poll for cancellation.

You need some protection against re-entering doWork() from this event queue.  One way to manage this is with a tiny state-machine:

private:
    enum State { IDLE, RUNNING, PAUSED };
    State state = IDLE;


Used like this:

void MyWorker::doWork()
{
    if (state == RUNNING)
        return;

    state = RUNNING;
    emit started();




Here's my complete, tested version - no locks or atomics, all the synchronization is managed by Qt:

#include &lt;QAbstractEventDispatcher&gt;
#include &lt;QObject&gt;
#include &lt;QThread&gt;
#include &lt;QDebug&gt;

class Worker : public QObject
{
    Q_OBJECT

public:
    explicit Worker(QObject *parent = 0)
        : QObject(parent)
    {
    }

signals:
    void started();
    void finished();

public slots:
    void pause()
    {
        auto const dispatcher = QThread::currentThread()-&gt;eventDispatcher();
        if (!dispatcher) {
            qCritical() &lt;&lt; "thread with no dispatcher";
            return;
        }

        if (state != RUNNING)
            return;

        state = PAUSED;
        qDebug() &lt;&lt; "paused";
        do {
            dispatcher-&gt;processEvents(QEventLoop::WaitForMoreEvents);
        } while (state == PAUSED);
    }

    void resume()
    {
        if (state == PAUSED) {
            state = RUNNING;
            qDebug() &lt;&lt; "resumed";
        }
    }

    void cancel() {
        if (state != IDLE) {
            state = IDLE;
            qDebug() &lt;&lt; "cancelled";
        }
    }

protected:

    enum State { IDLE, RUNNING, PAUSED };
    State state = IDLE;

    bool isCancelled() {
        auto const dispatcher = QThread::currentThread()-&gt;eventDispatcher();
        if (!dispatcher) {
            qCritical() &lt;&lt; "thread with no dispatcher";
            return false;
        }
        dispatcher-&gt;processEvents(QEventLoop::AllEvents);
        return state == IDLE;
    }

};


class MyWorker : public Worker
{
    Q_OBJECT

public:
    explicit MyWorker(QObject *parent = 0)
        : Worker(parent)
    {
    }

    void doWork()
    {
        if (state == PAUSED)
            // treat as resume
            state = RUNNING;

        if (state == RUNNING)
            return;

        state = RUNNING;
        qDebug() &lt;&lt; "started";
        emit started();

        // This loop simulates the actual work
        for (auto i = 0u;  state == RUNNING;  ++i) {
            QThread::msleep(100);
            if (isCancelled()) break;
            qDebug() &lt;&lt; i;
        }

        qDebug() &lt;&lt; "finished";
        emit finished();
    }
};


#include &lt;QCoreApplication&gt;
int main(int argc, char **argv)
{
    QCoreApplication app(argc, argv);

    QThread thread;
    auto worker = new MyWorker();
    worker-&gt;moveToThread(&amp;thread);
    QObject::connect(&amp;thread, &amp;QThread::started, worker, &amp;MyWorker::doWork);
    QObject::connect(worker, &amp;MyWorker::finished, worker, &amp;QObject::deleteLater);
    QObject::connect(worker, &amp;QObject::destroyed, &amp;thread, &amp;QThread::quit);
    QObject::connect(&amp;thread, &amp;QThread::finished, &amp;app, &amp;QCoreApplication::quit);

    thread.start();

    // To saved defining more signals, I'll just use invoke() here.
    // Normally, we connect some "driver" object's signals to the
    // pause/resume/cancel slots.
    auto const m = worker-&gt;metaObject();
    QThread::sleep(1);
    m-&gt;invokeMethod(worker, "pause");
    QThread::sleep(4);
    m-&gt;invokeMethod(worker, "resume");
    QThread::sleep(1);
    m-&gt;invokeMethod(worker, "cancel");

    app.exec();
}


Sorry this is a bit rushed; I hope the principle is clear.