Почему мой вложенный QEventLoop не доставляет все события для моего QThread? - PullRequest
2 голосов
/ 02 сентября 2010

У меня проблема с QEventLoop. Я хочу создать TimeBoundExerciser для моего модульного теста, чтобы моя SUT, которая блокирует QEventLoop, не блокировала остальные тестовые случаи. В частности, мой тестовый пример - убедиться, что SUT завершает работу после тайм-аута.

TimeBoundExerciser в основном порождает поток, выполняет SUT в этом потоке, ожидает завершения потока и, если он не завершается через определенное время, вызывает метод quit () для потока через QMetaObject: : invokeMethod () и QueuedConnection. Я ожидал бы, что выполнение quit () приведет к тому, что мой вложенный QEventLoop завершит работу, завершив мой поток. Однако я обнаружил, что метод quit () никогда не вызывается и поток никогда не завершается. Код для моего 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;
}

Метод упражнения () выполняется в главном потоке, чтобы запустить весь процесс.

1 Ответ

0 голосов
/ 02 сентября 2010

Если тест выполняется слишком долго, он, вероятно, находится в некотором цикле обработки данных.

Естественно, ваш запрос на выход не будет доставлен, потому что тестовый поток занят выполнением теста. Сообщения не прерывают потоки, они обрабатываются, когда поток заканчивает обработку предыдущего сообщения и возобновляет цикл событий.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...