Domanda

Ho una classe, che è un'astrazione di alcuni dispositivi.

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

signals:
  void sMsgArrived();
}  

Start () e stop () sono chiamati dal thread GUI. Start () inizia un nuovo thread, che esegue msGloop (). Sembra questo:

void MsgLoop()  
{
   forever {  
      if(SUCCESS == ReadMsg()) //synchronous, non-blocking
      {
        ProcessMsg(); //quite fast
        emit sMsgArrived(); //this signal is connected with a slot in GUI thread  
      }
   }
}

Quando viene chiamato stop (), il programma dovrebbe tornare da msGloop () e arrestare il thread. Come posso implementarlo con QThread senza sottoclassirlo?

È stato utile?

Soluzione

Generalmente devi decidere chi sarà responsabile della gestione del thread. È il dispositivo o la finestra principale? O forse un gestore di dispositivi. Nel tuo caso il dispositivo dovrebbe probabilmente gestire il proprio thread, quindi se non si desidera sottoclassare, utilizzare la composizione:

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();
}

Nota: la fermo thread funzionerà solo se ReadMsg davvero non blocca. Se in seguito decidi di passare al blocco della lettura (e questo sarebbe probabilmente appropriato per la maggior parte dei casi), dovrai capire un altro modo per fermare il thread.

Altri suggerimenti

Se guardi questo collegamento Puoi vedere che è possibile eseguire un metodo in un thread separato senza sottoclasse un QThread.

Tuttavia, quello che stai chiedendo è eseguire un ciclo di messaggi per sempre.

Se segui l'esempio fornito puoi eseguire il tuo loop senza la sottoclasse ma l'oggetto QThread non entrerà mai nel suo proprio ciclo di messaggi Perché non tornerà mai dallo slot. Quindi ecco un esempio ma penso che sarebbe un cattivo disegno

class Device : public QObject
{
Q_OBJECT

public:
Device(QObject* parent = 0);
~Device();

public Q_SLOTS:
  void MsgLoop();

};

QThread* thread = new QThread;
Device* device = new Device;

void Widget::onBtnStartClicked()
{

    device->moveToThread(thread);

    //This will call start method of Device
    connect(thread, SIGNAL(started()), device, SLOT(MsgLoop()));

    //This will start the event loop of thread
    thread->start();
}

void Widget::onBtnStopClicked()
{
 //Tells the thread to exit
 thread->exit(0);

}

Temo che tu debba sottoclasse un QThread se vuoi eseguire un per sempre ciclo continuo.

Imho non dovresti. Il sondaggio richiede di essere in un ciclo per sempre. È necessario farlo nella funzione di corsa di QThread, quindi non c'è modo di reimplementare una funzione senza prima sottoclasse. Anche se dovessi provare a lavorare con un singolo timer, non lo consiglio. Stai meglio (è così che mi piace farlo) sotto-classicante QThread, chiamando MoveTothRead (), non Call Exec () e metti un giro per sempre in corsa. Per un esempio di questo sguardo all'esempio del client bloccante della fortuna da Qt. Se non si chiama MoveToThRead () su QThread, l'oggetto QThread risiede ancora nel thread principale della GUI ed entrambi condividono lo stesso ciclo di eventi (che è cattivo quando si utilizzano funzioni di polling). Chiamare MoveTothRead (QThread) senza chiamare Exec () significa che QThread non avrà un ciclo di eventi (che è buono nel tuo caso). Calling Exec () inizierebbe il proprio ciclo di eventi ma non è utilizzato per i sistemi di sondaggi e lasci la funzione di corsa.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top