Pergunta

Na minha aplicação, há o segmento principal e um segmento de trabalho (QThread).
A partir do thread principal que eu gostaria de chamar um método do meu segmento de trabalho e executá-lo no contexto do segmento.

Eu tentei usar QMetaObject::invokeMethod e dar-lhe a opção QueuedConnection mas ele não está funcionando.
Eu também tentei emissor de sinais do segmento principal (que está ligado à ranhura do segmento de trabalho), mas que também falhou.

Aqui está um trecho de aproximadamente o que eu tentei:

class Worker : public QThread
{
    Q_OBJECT

public:
    Worker() { }

    void run() 
    { 
        qDebug() << "new thread id " << QThread::currentThreadId(); 
        exec(); 
    }

public slots:
    void doWork()
    {
        qDebug() << "executing thread id - " << QThread::currentThreadId();
    }
};

Usando o caminho QMetaObject:

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    qDebug() << "main thread id - " << QThread::currentThreadId();

    Worker worker;
    worker.start();

    QMetaObject::invokeMethod(&worker, "doWork", Qt::QueuedConnection);

    return a.exec();
}

Usando o caminho de sinal:

class Dummy : public QObject
{
    Q_OBJECT

public:
    Dummy() { }

public slots:
    void askWork() { emit work(); }

signals:
    void work();
};

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    qDebug() << "main thread id - " << QThread::currentThreadId();

    Worker worker;
    worker.start();

    Dummy dummy;
    QObject::connect(&dummy, SIGNAL(work()), &worker, SLOT(doWork()), Qt::QueuedConnection);

    QTimer::singleShot(1000, &dummy, SLOT(askWork()));

    return a.exec();
}

Ambas as formas resultar na principal identificador do tópico que está sendo impresso na QThread doWork.

Além disso, eu pensei de implementação de um produtor-consumidor simples, mas se isso funciona, há alguma razão para não fazê-lo desta maneira?

Foi útil?

Solução

O problema era que o receptor (o QThread) 'vidas' no thread principal e, portanto, ciclo de eventos principal do segmento é aquele que executa o slot.

a partir de docs do Qt:

Com conexões em fila, a ranhura é invocado quando o controle retorna para o ciclo de eventos do fio para que o objecto pertence. O slot é executado no segmento onde as vidas objeto receptor.

Assim, a solução que eu encontrei até agora foi criar um objeto dentro prazo do segmento () e usar seus slots vez. Dessa forma, o dono do receptor é o fio e, em seguida, o slot é chamado no contexto threads.

Outras dicas

Este exemplo mostra como você pode dividir a classe do trabalhador, para que ele funcione como você quer. Você também precisa fazer referência a disponível ou ponteiro para a instância do trabalhador para ser capaz de conectar-se ao slot.

class Worker : public QObject
{
    Q_OBJECT

public:
    Worker() { }

public slots:
    void doWork()
    {
        qDebug() << "executing thread id - " << QThread::currentThreadId();
    }
};

class WorkerThread : public QThread
{
    Q_OBJECT

public:
    void run()
    {
        qDebug() << "new thread id " << QThread::currentThreadId(); 
        Worker worker;
        exec();
    }
};

Para o exemplo simples produtor-consumidor, ter um olhar para a entrada de blog a partir de Bradley T. Hughes Treading sem a dor de cabeça .

O trabalhador é criado no thread principal e, portanto, de eventos são proccessed no segmento principal. Você deve mover o trabalhador a seu próprio fio:

Worker worker;
worker.moveToThread(&worker);
worker.start();

Agora Qt sabe vidas worker no novo segmento, e a fila eventos nesse ciclo de eventos.

Parece que seus concluída thread de trabalho antes que você pode até mesmo invocar qualquer função ou enviar um sinal para ele.

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