有没有办法从QML WorkerScript运行C ++?

时间:2017-10-13 22:21:01

标签: c++ multithreading qt qml

我需要从QML UI控制慢速I / O操作。 I / O接口是C ++。基本上,当用户按下按钮时,我需要发送消息并从设备获得响应。我希望用户在等待响应时能够做其他事情。 WorkerScript似乎是实现这一目标的最简单方法,但是如何将我的C ++接口放入脚本中,因为正常的QDeclarativeContext没有传入线程?有没有办法将C ++导入QML的javascript?我甚至不需要在主线程中维护C ++上下文,我可以完全生活在工作者中并且只是来回传递消息。 编辑:
澄清:@dtech的答案满足了我目前的需求,但我仍然想知道这个问题的答案:是否有可能将C ++(即使没有状态)转换为WorkerScript。

1 个答案:

答案 0 :(得分:1)

如果您可以选择将QObject放入专用线程,在不阻塞主线程的情况下执行代码,并且不同步地来回传递和交付结果,为什么会这样做呢?

您不需要WorkerScript,也不是它的预期用途。既然您的代码仍然是C ++,那么您只需要QThreadQObject

这是一个简单的例子:

class Worker : public QObject {
    Q_OBJECT
  public slots:
    void doWork() {
      int i = 0;
      while (i < 100) {
        result(i++);
        std::this_thread::sleep_for(std::chrono::milliseconds(500));
      }
    }
  signals:
    void result(int r);
};

class Controller : public QObject {
    Q_OBJECT
  public:
    Controller() {
      w = new Worker;
      t = new QThread;
      w->moveToThread(t);
      connect(this, SIGNAL(start()), w, SLOT(doWork()));
      connect(w, SIGNAL(result(int)), this, SIGNAL(result(int)));
      t->start();
    }
  private:
    Worker * w;
    QThread * t;
  signals:
    void start();
    void result(int r);
};

// in main.cpp
  Controller cw;
  engine.rootContext()->setContextProperty("Work", &cw);
  engine.load(QUrl(QStringLiteral("qrc:/main.qml"))); // load main qml


// QML

  Column {
    Button {
      id: start
      onClicked: Work.start()
    }
    Text {
      id: res
    }
  }

  Connections {
    target: Work
    onResult: res.text = r
  }

这是一个简单的阻塞工作程序,它将阻塞其线程约50秒,但仍然能够发出将在QML端更新的结果,同时保持GUI线程空闲。请注意,一旦调用了工作函数,就无法以任何方式中断,暂停或控制它,如果需要,则必须实现non-blocking worker。也不需要C ++控制器作为QML和“线程对象”之间的中介,因为看起来QML不能直接与这些对象相处。