目前我正在开发一种基于flex& bison的简单编程语言。
为此,我首先构建抽象语法树(AST)并继续其评估。在评估期间,应该可以接收用户输入。用户输入在Qt-GUI中完成。 ast-evaluation-procedure在一个由GUI创建的thread-worker-object中运行。 我的问题:哪一个是最好的方式,以及#34;阻止"然后运行flex& Bison评估程序从GUI接收用户输入,然后继续执行程序? 不幸的是,我不知道如何将评估程序分成两部分来捕获来自GUI的用户输入信号,然后继续使用"拆分程序"在一个插槽中。 我的当前解决方案(在我看来很差)在评估过程中使用无限循环,直到线程worker-object中的布尔成员变量(_hasUserInput)设置为true。在用户输入之后,GUI发出信号。相应的槽位于线程工作者对象内。该插槽接收用户输入,例如作为QString并设置相应的成员变量。此外,布尔变量设置为true,因此可以保留评估过程的无限循环,可以处理用户输入并继续评估。
功能原理:
GUI - >启动线程(工作者对象) - >启动长期运行程序
伪代码中的示例:
class ThreadWorker : public QObject {
...
// Slot, that reacts to the signal from the GUI
void userInput(const QString &input) {
_userInput = input;
_hasUserInput = true;
}
// evaluation-procedure
void doEvaluation() {
// evaluation of the AST
...
emit userInputRequired();
while (!hasUserInput){ // Check if user input has been done
qApp -> processEvents(); // to react to events
}
do something with user input;
continue valuation; // Processing of user input and continuation of the procedure
}
...
};
我试着尽可能好地描述我的问题并希望它有效。如果您需要更详细的信息,请询问。 非常感谢您的帮助!
答案 0 :(得分:0)
由于您已经将工作人员分解为QObject
,因此您永远不需要致电processEvents()
。相反,将AST评估分解为只需要执行的小块。我还使公共接口成为线程安全的 - 因此您可以直接从任何线程调用它。
// see https://stackoverflow.com/a/40382821/1329652
bool isSafe(QObject * obj);
template <typename Class, typename... Args> void postCall(Class * obj, void (Class::*method)(Args...), Args&& ...args);
class ASTWorker : public QObject {
Q_OBJECT
QBasicTimer m_evaluateTimer; // a bit lower overhead than QTimer
void timerEvent(QTimerEvent * ev) override {
if (ev->timerId() == m_evaluateTimer.timerId())
evaluateImpl();
}
void evaluateImpl() {
bool evaluationDone = {};
QThread::msleep(10); // emulate evaluating a chunk of AST
if (!evaluationDone && !m_evaluateTimer.isActive())
m_evaluateTimer.start(0, this);
else if (evaluationDone)
m_evaluateTimer.stop();
}
public:
using QObject::QObject;
/// Thread-safe
Q_SLOT void setUserInput(const Data & data) {
if (!isSafe(this))
return postCall(this, &ASTWorker::setUserInput, data);
QThread::msleep(1); // emulate processing user data
}
/// Thread-safe
Q_SLOT void evaluate() {
if (!isSafe(this))
return postCall(this, &ASTWorker::evaluate, data);
evaluateImpl();
}
};