简体   繁体   English

为什么我的嵌套QEventLoop无法为QThread传递所有事件?

[英]Why won't my nested QEventLoop deliver all the events for my QThread?

I'm having a problem with QEventLoop. 我在使用QEventLoop时遇到问题。 I want to create a "TimeBoundExerciser" for my unit test so that my SUT, which blocks on a QEventLoop, won't block the rest of the test cases. 我想为单元测试创​​建一个“ TimeBoundExerciser”,以使在QEventLoop上阻止的SUT不会阻止其余的测试用例。 Specifically, my test case is to make sure the SUT terminates after a timeout. 具体来说,我的测试用例是确保SUT在超时后终止。

The TimeBoundExerciser basically spawns a thread, executes the SUT on that thread, waits for the thread to terminate, and if it doesn't terminate after a specific amount of time, invokes the quit() method on the thread through QMetaObject::invokeMethod() and a QueuedConnection. TimeBoundExerciser基本上产生一个线程,在该线程上执行SUT,等待该线程终止,如果在特定时间后仍未终止,则通过QMetaObject :: invokeMethod()在该线程上调用quit()方法。 )和QueuedConnection。 I would expect that executing quit() will cause my nested QEventLoop to exit, terminating my thread. 我希望执行quit()会导致嵌套的QEventLoop退出,从而终止我的线程。 However, what I've found is that the quit() method is never invoked, and the thread never terminates. 但是,我发现,永远不会调用quit()方法,并且线程永远不会终止。 The code for my TimeBoundExerciser is below: 我的TimeBoundExerciser的代码如下:

class IExerciseTheSystem
{
    void operator()() = 0;
};

class TimeBoundExerciser : private QThread
{
Q_OBJECT
public:
    enum CompletionType
    {
        TERMINATED,
        FORCE_QUIT,
        QUIT
    };
    TimeBoundExerciser(const IExerciseTheSystem& exerciser);
    CompletionType exercise(unsigned long timeoutMillis);   
protected:
    void run();

protected slots:
    void exerciseTheSystem();
private:
    const IExerciseTheSystem& exerciser;
};

TimeBoundExerciser::TimeBoundExerciser(const IExerciseTheSystem& exerciser) : exerciser(exerciser)
{

}

TimeBoundExerciser::CompletionType TimeBoundExerciser::exercise(unsigned long timeoutMillis)
{
    start();
    while (!isRunning()) 
    {
        msleep(10);
    }

    moveToThread(this);

    wait(timeoutMillis);
    if (!isFinished()) 
    {
        bool quitResult;
        QMetaObject::invokeMethod(this, "quit", Qt::QueuedConnection, Q_RETURN_ARG(bool, quitResult));
        wait();
        return FORCE_QUIT;
    }

    return QUIT;
}

void TimeBoundExerciser::run()
{
    setTerminationEnabled(true);
    QMetaObject::invokeMethod(this, "exerciseTheSystem", Qt::QueuedConnection);
    exec();
}

void TimeBoundExerciser::exerciseTheSystem()
{
    cout << "Starting exerciser" << endl;
    exerciser();
    cout << "Exerciser ended" << endl;
}

The exercise() method is executed on the main thread to kick off the whole process. exercise()方法在主线程上执行,以启动整个过程。

If the test runs too long, it's probably in some sort of loop processing data. 如果测试运行时间过长,则可能是某种形式的循环处理数据。

Naturally, your quit request won't be delivered because the test thread is busy running the test. 当然,由于测试线程正忙于运行测试,因此不会发出您的退出请求。 Messages don't interrupt threads, they are processed when the thread finishes processing the previous message and resumes the event loop. 消息不会中断线程,当线程完成对上一条消息的处理并恢复事件循环时,将对其进行处理。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM