首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >自定义函数中断

自定义函数中断
EN

Stack Overflow用户
提问于 2016-12-04 15:13:06
回答 2查看 398关注 0票数 0

是否可以在Qt (5.x)中实现函数中断。

例如,如果我有一个按钮,并希望在单击该按钮时在线程上执行某项操作(该线程正在运行无限循环),我可以这样说:

代码语言:javascript
复制
in thread...
forever
{
  if(button_is_pressed_flag)
  {
    do something...
  }
}

有更好的办法吗?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2016-12-05 14:33:54

无限循环应该是一个事件循环,然后它可以自动处理跨线程插槽调用,而不必担心细节。

在事件循环上“连续”运行代码的成语是零持续计时器。

假设您从如下代码开始:

代码语言:javascript
复制
class MyThread : public QThread {
  bool button_is_clicked_flag = false;
  void run() override {
    forever{
      if (button_is_clicked_flag) {
        onButtonClick();
        button_is_clicked_flag = false;
      }
      doWork();
    }
  }
  void onButtonClick();
  void doWork();
public:
  using QThread::QThread;
  void setButtonClickedFlag();
}

int main(int argc, char **argv) {
  ...
  MyThread t;
  t.start();
  ...
}

要求doWork()不要花费太长时间--也不要太短。如果它在现代硬件上花费了5ms,那么对于一个通用的应用程序来说,它将是在开销和延迟之间的一个正确的权衡。如果在工作线程中需要较低的延迟反应,那么doWork()必须少做一些工作。对于doWork()来说,花费少于1ms的时间可能没有多大意义。

而且,每当doWork()没有任何事情可做时,例如,如果它完成了它应该执行的计算,它就应该停止使它保持活力的计时器。

您应该将其转换为如下所示:

代码语言:javascript
复制
class MyWorker : public QObject {
  Q_OBJECT
  QBasicTimer m_timer;
  void doWork();
  void timerEvent(QTimerEvent *event) {
    if (event->timerId() == m_timer.timerId())
      doWork();
  }
public:
  explicit MyWorker(QObject *parent = nullptr) : QObject(parent) {
    m_timer.start(0, this);
  }
  Q_SLOT void onButtonClick() {
    // Ensure we're invoked correctly
    Q_ASSERT(QThread::currentThread() == thread());
    ...
  }
}

class Window : public QWidget {
  Ui::Window ui;
public:
  Q_SIGNAL void buttonClicked();
  explicit Window(QWidget *parent = nullptr) : QWidget(parent) {
    ui.setupUi(this);
    connect(ui.button, &QPushButton::clicked, this, &Window::buttonClicked);
  }
};

class SafeThread : public QThread {
  Q_OBJECT
  using QThread::run; // final method
public:
  ~SafeThread() { quit(); wait(); } // we're safe to destroy - always
};

int main(int argc, char **argv) {
  ...
  MyWorker worker;
  SafeThread thread;
  Window window;
  // onButtonClick will be executed in worker->thread()
  connect(&window, &Window::buttonClicked, &worker, &MyWorker::onButtonClick);
  worker.moveToThread(&thread);
  thread.start();
  window.show();
  return app.exec();
}

QThread::run中运行的事件循环将通过计时器事件处理程序持续调用doWork。但是,每当需要对驻留在该线程中的对象进行跨线程时隙调用时,事件循环将将表示时隙调用的内部QMetaCallEvent传递给QObject::event,后者将执行调用。

因此,当您在onButtonClick中设置断点时,调用堆栈附近将有QObject::event

票数 3
EN

Stack Overflow用户

发布于 2016-12-04 16:09:41

您可以启动一个线程,然后立即等待一个std::condition_variable,然后单击按钮(主线程上正在调用的事件),通知条件变量,线程就会苏醒。

不过,这有点奇怪。你想做什么?在单击按钮时调用异步任务?在这种情况下,使用std::packaged_task或std::异步从单击按钮事件启动一个可能更好。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/40960064

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档