Pergunta

A documentação do QT afirma que sinais e slots podem ser direct, queued e auto.

Ele também afirmou que, se o objeto que possui o slot 'vidas' em um fio diferente de objeto que possui sinal, a emissão desse sinal será como postar a mensagem - a emitir o sinal retornará instantaneamente e o método de slot será chamado no loop de eventos do thread do destino.

Infelizmente, a documentação não especifica que 'vidas' representa e nenhum exemplo está disponível. Eu tentei o seguinte código:

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

A saída é:

thread 2 started
thread 1 started

MySlot() nunca é chamado :(. O que estou fazendo de errado?

Foi útil?

Solução

Existem alguns problemas com seu código:

  • como dito por Evan, a palavra -chave emit está faltando
  • Todos os seus objetos vivem no tópico principal, apenas o código nos métodos de execução vivem em outros tópicos, o que significa que o slot myslot seria chamado no tópico principal e não tenho certeza se é isso que você quer
  • Seu slot nunca será chamado, já que o loop de evento principal nunca será lançado: suas duas chamadas para esperar () só limitarão depois de muito tempo (e você provavelmente matará seu aplicativo antes que isso aconteça) e eu não acho que não Isso é o que você quer, de qualquer maneira, eles realmente não têm utilidade no seu código.

Esse código provavelmente funcionaria (embora eu não o tenha testado) e acho que faz o que você deseja fazer:

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

Agora o MyObject viverá em Thread2 (graças ao MoveTothread).

O MySignal deve ser enviado do Thread1 (pensei que não tenho certeza disso, ele pode ser enviado do thread principal, isso realmente não importa).

Nenhum loop de evento é necessário no Thread1, pois a emitir um sinal não precisa de um loop de eventos. Um loop de evento é necessário no Thread2 (encenado pelo EXEC ()) para receber o sinal.

Myslot será chamado no Thread2.

Outras dicas

Não subclasse qthread para qt 4.4+

Embora a resposta da AIUA seja boa, quero apontar alguns problemas com o QTHREAD e o QT 4.6 ou 4.7.

Este artigo resume: http://blog.qt.io/blog/2010/06/17/youre-doing-it-wrong/

Falta de documentação da parte do QT

Infelizmente, o problema decorre da falta de atualizações para a documentação. Antes do QT 4.4, o QTHREAD não possuía implementação padrão RUN (), o que significava que você precisava subclasse o QTHREAD para usá -lo.

Se você está usando o Qt 4.6 ou 4.7, então quase certamente deveria não Subclasse Qthread.

Use MoveTothread

A chave para obter slots a serem executados em um thread trabalhador é usar o método MoveTothread como apontou a AIUA.

você deve emitir o sinal para iniciar sua função de thread como

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

Você pode adicionar mais de um argumento neste sinal

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top