我有一个类,它是某些设备的抽象。

class Device
{
public:
  ...
  void Start();
  void Stop();
  void MsgLoop();

signals:
  void sMsgArrived();
}

从GUI线程调用Start()和Stop()。 Start()开始新线程,该线程运行MsgLoop()。看起来像这样:
void MsgLoop()
{
   forever {
      if(SUCCESS == ReadMsg()) //synchronous, non-blocking
      {
        ProcessMsg(); //quite fast
        emit sMsgArrived(); //this signal is connected with a slot in GUI thread
      }
   }
}

调用Stop()时,程序应从MsgLoop()返回并停止线程。如何在不子类化的情况下用QThread实现呢?

最佳答案

通常,您必须确定谁将负责管理线程。是设备还是主窗口?或者可能是一些设备管理器。在您的情况下,设备可能应该管理自己的线程,因此,如果您不想对其进行子类化,请使用composition:

class Device : QObject
{
    Q_OBJECT
public:
    Device(QObject * parent = NULL);
    void Start();
    void Stop();

private slots:
    void MsgLoop();

signals:
    void sMsgArrived();

private:
    QThread thread;
    bool stopThread;
};


Device::Device(QObject * parent) : QObject(parent)
{
    moveToThread(&thread);
    connect(&thread, SIGNAL(started()), this, SLOT(MsgLoop()));
}

void Device::Start()
{
    stopThread = false;
    thread.start();
}

void Device::Stop()
{
    stopThread = true;
    thread.wait();      // if you want synchronous stop
}

void Device::MsgLoop()
{
  // your loop
  while(!stopThread)
    if(SUCCESS == ReadMsg())
    {
      ProcessMsg();
      emit sMsgArrived();
    }
  QThread::currentThread->quit();
}

注意:只有在ReadMsg确实是非阻塞的情况下,线程停止才会起作用。如果您以后决定切换到阻止读取(这在大多数情况下可能是适当的),那么您将不得不找出另一种方法来停止线程。

10-08 07:54