Domanda

La documentazione di Qt afferma che i segnali e gli slot possono essere diretti , in coda e auto .

Ha anche affermato che se l'oggetto che possiede lo slot "vive" in un thread diverso dall'oggetto che possiede il segnale, l'emissione di tale segnale sarà come l'invio di un messaggio - l'emissione del segnale tornerà istantaneamente e il metodo dello slot verrà chiamato nel loop degli eventi del thread di destinazione .

Sfortunatamente, la documentazione non specifica che "vita" rappresenta e non sono disponibili esempi. Ho provato il seguente codice:

main.h:

class CThread1 : public QThread
{
Q_OBJECT
public:
    void run( void )
    {
        msleep( 200 );
        std::cout << "thread 1 started" << std::endl;
        MySignal();
        exec();
    }
signals:
    void MySignal( void );
};

class CThread2 : public QThread
{
Q_OBJECT
public:
    void run( void )
    {
        std::cout << "thread 2 started" << std::endl;
        exec();
    }
public slots:
    void MySlot( void )
    {
        std::cout << "slot called" << std::endl;
    }
};

main.cpp:

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    CThread1 oThread1;
    CThread2 oThread2;
    QObject::connect( & oThread1, SIGNAL( MySignal() ),
        & oThread2, SLOT( MySlot() ) );
    oThread1.start();
    oThread2.start();
    oThread1.wait();
    oThread2.wait();
    return a.exec();
}

L'output è:

thread 2 started
thread 1 started

MySlot () non viene mai chiamato :(. Cosa sto facendo di sbagliato?

È stato utile?

Soluzione

Ci sono alcuni problemi con il tuo codice:

  • come detto da Evan manca la parola chiave emit
  • tutti i tuoi oggetti vivono nel thread principale, solo il codice nei metodi di esecuzione vive in altri thread, il che significa che lo slot MySlot sarebbe chiamato nel thread principale e non sono sicuro che sia quello che vuoi
  • il tuo slot non verrà mai chiamato poiché il loop degli eventi principali non verrà mai avviato: le tue due chiamate ad wait () si interromperanno solo dopo molto tempo (e probabilmente ucciderai la tua applicazione prima che ciò accada) e io pensate che sia quello che volete, comunque non hanno davvero alcuna utilità nel vostro codice.

Molto probabilmente questo codice funzionerebbe (anche se non l'ho testato) e penso che faccia quello che vuoi che faccia:

class MyObject : public QObject
{
    Q_OBJECT
public slots:
    void MySlot( void )
    {
        std::cout << "slot called" << std::endl;
    }
};

class CThread1 : public QThread
{
    Q_OBJECT
public:
    void run( void )
    {
        std::cout << "thread 1 started" << std::endl;
        int i = 0;
        while(1)
        {
           msleep( 200 );
           i++;
           if(i==1000)
              emit MySignal();
        }
    }
signals:
    void MySignal( void );
};

class CThread2 : public QThread
{
    Q_OBJECT
public:
    void run( void )
    {
        std::cout << "thread 2 started" << std::endl;
        exec();
    }
};

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    CThread1 oThread1;
    CThread2 oThread2;
    MyObject myObject;
    QObject::connect( & oThread1, SIGNAL( MySignal() ),
        & myObject, SLOT( MySlot() ) );
    oThread2.start();
    myObject.moveToThread(&oThread2)
    oThread1.start();
    return a.exec();
}

Ora MyObject vivrà in thread2 (grazie a moveToThread).

MySignal dovrebbe essere inviato da thread1 (pensato che non sono sicuro su quello, potrebbe essere inviato dal thread principale, non importa davvero).

Non è necessario alcun loop di eventi in thread1 poiché l'emissione di un segnale non richiede un loop di eventi. Per ricevere il segnale è necessario un loop di eventi in thread2 (concesso in licenza da exec ()).

MySlot verrà chiamato in thread2.

Altri suggerimenti

Non eseguire la sottoclasse di QThread per Qt 4.4+

Mentre la risposta di Aiua è buona, voglio evidenziare alcuni problemi con QThread e Qt 4.6 o 4.7.

Questo articolo lo riassume: http: / /blog.qt.io/blog/2010/06/17/youre-doing-it-wrong/

Mancanza di documentazione da parte di Qt

Sfortunatamente il problema deriva da una mancanza di aggiornamenti alla documentazione. Prima di Qt 4.4 QThread non aveva un'implementazione run () predefinita, il che significava che era necessario sottoclassare QThread per usarlo.

Se stai usando Qt 4.6 o 4.7, quasi sicuramente dovresti non sottoclasse QThread.

Usa moveToThread

La chiave per ottenere gli slot da eseguire in un thread di lavoro è usare il metodo moveToThread come ha sottolineato Aiua.

dovresti emettere il segnale per avviare la tua funzione thread come

emit operateCut(examId,examName_examTemplate[examName].studentIdRec,examName_examTemplate[examName].choiceRecA,examName_examTemplate[examName].choiceRecB,examName_examTemplate[examName].objectRecA,examName_examTemplate[examName].objectRecB);

puoi aggiungere più di un argomento in questo segnale

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