Invocando métodos no contexto QThread
-
06-07-2019 - |
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?
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.