Re: Call function of object within Threads.
Hello everyone.
I'm studying about threads and would like some help.
Learn how to perform functions that are on an object that has been moved to a thread.
I have to pass parameters to the function and receive the return of it to be able to display in a text edit.
Oops: Forgetting that objects and threads are generated by a "FOR".
first......: How to pass parameters to the function ???
second.: How to receive the return of it to be able to display in a text edit ???
I tried this:
Code:
void MainWindow::on_cmdIniciar_clicked()
{
// ARRAY DE THREADS
// ARRAY DE OBJETOS
clsTask *vobjTask[vnumCont];
for(int vnumIni=0; vnumIni < vnumCont; vnumIni++)
{
vobjTask[vnumIni] = new clsTask();
vthrThread
[vnumIni
] = new QThread();
//ERRO HERE
//QObject::connect(&vthrThread[vnumIni], SIGNAL(started), vobjTask[vnumIni], SLOT(fcMensagemTexto(QString::number(vnumIni))));
vobjTask[vnumIni]->moveToThread(vthrThread[vnumIni]);
vthrThread[vnumIni]->start();
}
Code:
QObject::connect(&vthrThread
[vnumIni
],
&QThread
::started,
&vobjTask
[vnumIni
],
&clsTask
::fcMensagemTexto(QString::number(vnumIni
) ));
ERRO:
cannot call member function 'QString clsTask::fcMensagemTexto(QString)' without object
QObject::connect(&vthrThread[vnumIni], &QThread::started, &vobjTask[vnumIni], &clsTask::fcMensagemTexto(QString::number(vnumI ni) ));
COMPILER OUTPUT
error: cannot call member function 'QString clsTask::fcMensagemTexto(QString)' without object
QObject::connect(&vthrThread[vnumIni], &QThread::started, &vobjTask[vnumIni], &clsTask::fcMensagemTexto(QString::number(vnumI ni) ));
Re: Call function of object within Threads.
If the thread has a single function and only executes it once, just pass the arguments to the class constructor.
You can also use QMetaObject::invokeMethod() with connection type Qt::QueuedConnection to invoke a slot on the worker object in the worker thread's context.
For the result you either need a signal on the worker object or use the invokeMethod() option the other way around on an object that belongs to the main thread.
Cheers,
_
Re: Call function of object within Threads.
Hi, anda_skoa.
First of all, thank you for answering me.
Before reading your considerations, I was modifying the project to simplify it and thus better understand how to work with threads and why it is giving error.
You could take a look to see where I'm going wrong, the project was like this.
Thank you for your attention.
Code:
// Arquivo .h
#include <QObject>
#include <QThread>
{
Q_OBJECT
public:
clsThrTask
(QString pstrIdThread,
QObject *parent
= nullptr
);
// Constructor with paramenter void run() override;
signals:
Code:
//Arquivo .cpp
#include "clsthrtask.h"
{
vstrForRef = pstrIdThread;
}
void clsThrTask::run()
{
QString vstrResposta
= "Threads nº: " + QString::number((long long) QThread::currentThreadId(),
16) + " | FOR REF nº: " + vstrForRef;
// EMITE UM SIGNAL WITH DATA
emit sigRetorno(vstrResposta);
}
Code:
//Arquivo MainWindow.h
#include "clsthrtask.h"
namespace Ui {
class MainWindow;
}
class clsThrTask;
{
Q_OBJECT
public:
explicit MainWindow
(QWidget *parent
= nullptr
);
~MainWindow();
Code:
//Arquivo MainWindow.cpp
MainWindow
::MainWindow(QWidget *parent
) : ui(new Ui::MainWindow)
{
ui->setupUi(this);
}
// ARRAY OF THREADS
for(int vnumIni=0; vnumIni < vnumCont; vnumIni++)
{
vthrThread
[vnumIni
] = new QThread(QString::number(vnumIni
));
// Erro here. QObject::connect(vthrThread
[vnumIni
],
&clsThrTask
::sigRetorno, ui
->txtResultado,
&QTextEdit
::append);
// Erro here. vthrThread[vnumIni]->start();
}
1) error
: no matching function
for call to
'QThread::QThread(QString&)' vthrThread
[vnumIni
] = new QThread(vstrIdThread
);
2) error: invalid conversion from 'QThread*' to 'const Object* {aka const clsThrTask*}' [-fpermissive]
QObject::connect(vthrThread
[vnumIni
],
&clsThrTask
::sigRetorno, ui
->txtResultado,
&QTextEdit
::append);
^
Re: Call function of object within Threads.
Hi everyone
I found out where I was wrong, I'm talking about the first mistake.
VthrThread [vnumIni] = new QThread (vstrIdFor, this); Erro here.
VthrThread [vnumIni] = new clsMultiThr (vstrIdFor, this); Correct here.
Can someone help me in the second error.
Someone ???
2) Second erro is :
Code:
QObject::connect(vthrThread
[vnumIni
],
&clsMultiThr
::sigRetorno, ui
->txtResposta,
&QTextEdit
::append);
error: invalid conversion from 'QThread*' to 'const Object* {aka const clsMultiThr*}' [-fpermissive]
QObject::connect(vthrThread
[vnumIni
],
&clsMultiThr
::sigRetorno, ui
->txtResposta,
&QTextEdit
::append);
^
How would this connection work?
The neurons are dying and the blood is already in the shins. :D :D :D
Thank you for your attention.
Re: Call function of object within Threads.
Your array needs to be of the subtype as well.
In general you might want to prefer a container, e.g. a vector, over a C array.
Cheers,
_
Re: Call function of object within Threads.
Hi, Anda Skoa.
I will have to convert an array of threads to an array of objects
I'm not undestend, there is how to you show this in code for me to understand.
Thanks..
Re: Call function of object within Threads.
This:
Code:
// ARRAY OF THREADS
for(int vnumIni=0; vnumIni < vnumCont; vnumIni++)
{
vthrThread
[vnumIni
] = new QThread(QString::number(vnumIni
));
// Erro here. QObject::connect(vthrThread
[vnumIni
],
&clsThrTask
::sigRetorno, ui
->txtResultado,
&QTextEdit
::append);
// Erro here. vthrThread[vnumIni]->start();
}
needs to be this:
Code:
// ARRAY OF THREADS
clsThrTask *vthrThread[vnumCont];
for(int vnumIni=0; vnumIni < vnumCont; vnumIni++)
{
vthrThread
[vnumIni
] = new clsThrTask
(QString::number(vnumIni
));
QObject::connect(vthrThread
[vnumIni
],
&clsThrTask
::sigRetorno, ui
->txtResultado,
&QTextEdit
::append);
vthrThread[vnumIni]->start();
}
As anda_skoa said, your array of threads need to be of the same type as your derived class. The compiler is complaining because QThread does not have a signal named "sigRetorno".
Note that QTextEdit::append() is probably not an atomic method (that is, appending text is not protected by a mutex), so you could have two or more threads trying to modify the text edit at the same time. This could lead to memory corruption, a crash, or you might get lucky and it works just fine sometimes.
You would be better off connecting to a slot in your own class that protects the append() method from simultaneous access using a mutex.
1 Attachment(s)
Re: Call function of object within Threads.
Hi, d_stranz's.
I understood what you said, and it showed in code.
I tested it and it worked now.
Thank you very much for your explanation about the problem.
I will be making the project available on the site for other QT beginners,
To understand better about Threads.
Just to finalize this case study, I noticed that through Applications Output the following error message.
Code:
QObject: Cannot create children
for a parent that is in a different thread.
(Parent is
QProcess(0x239e2e0
), parent
's thread is QThread(0x1e16850), current thread is clsThrTask(0x239e300) QObject: Cannot create children for a parent that is in a different thread.
(Parent is QProcess(0x239e2e0), parent's thread is
QThread(0x1e16850
), current thread is clsThrTask
(0x239e300
) QObject: Cannot create children
for a parent that is in a different thread.
(Parent is
QProcess(0x239e2e0
), parent
's thread is QThread(0x1e16850), current thread is clsThrTask(0x239e300)
How do I resolve this?
Could you tell me what I should change in the code.
Thanks.
Re: Call function of object within Threads.
Quote:
Originally Posted by
d_stranz
Note that
QTextEdit::append() is probably not an atomic method (that is, appending text is not protected by a mutex), so you could have two or more threads trying to modify the text edit at the same time.
No problem in this case, as the signal/slot connection between two threads has the slot called in the context of the receiver object's thread.
So append() is always called by the same thread, in this case the main thread.
Quote:
Originally Posted by
marcos.miranda
Code:
QObject: Cannot create children
for a parent that is in a different thread.
(Parent is
QProcess(0x239e2e0
), parent
's thread is QThread(0x1e16850), current thread is clsThrTask(0x239e300) QObject: Cannot create children for a parent that is in a different thread.
(Parent is QProcess(0x239e2e0), parent's thread is
QThread(0x1e16850
), current thread is clsThrTask
(0x239e300
) QObject: Cannot create children
for a parent that is in a different thread.
(Parent is
QProcess(0x239e2e0
), parent
's thread is QThread(0x1e16850), current thread is clsThrTask(0x239e300)
You are probably passing "this" as the parent of an object that you create in "run()"
Edit: ah, no, you are creating the QProcess during class initialization, making it an object run by the main thread. You need to create it in run() or sltProcPing().
You should also be aware that sltPrintProcOut() is currently called by the main thread. If you want it called in the worker thread, you'll need to use a Qt::DirectConnection
Cheers,
_
Re: Call function of object within Threads.
Hi, Anda Skoa.
I modified Who was in (* .h) to
and put In sltProcPing as you recommended. It did right stopped the messages in Application Output.
Thanks, Thanks and Thanks.
1ª) question
When you said that sltPrintProcOut () is being called by the main thread and if I want it called in the worker thread, I'll need to use a "Qt:: DirectConnection", it was for I change the
Code:
connect (vprocPing, SIGNAL(readyReadStandardOutput()), this, SLOT(sltPrintProcOut()));
to
connect (vprocPing, SIGNAL(readyReadStandardOutput()), this, SLOT(sltPrintProcOut()),Qt::DirectConnection);
???
2ª) question
This would not cause problems with the Append method of the Response TextEdit, since some threads could call the method in question at the same time ???
Re: Call function of object within Threads.
Quote:
Originally Posted by
marcos.miranda
1ª) question
When you said that sltPrintProcOut () is being called by the main thread and if I want it called in the worker thread, I'll need to use a "Qt:: DirectConnection", it was for I change the
Code:
connect (vprocPing, SIGNAL(readyReadStandardOutput()), this, SLOT(sltPrintProcOut()));
to
connect (vprocPing, SIGNAL(readyReadStandardOutput()), this, SLOT(sltPrintProcOut()),Qt::DirectConnection);
???
Yes, correct.
Quote:
Originally Posted by
marcos.miranda
2ª) question
This would not cause problems with the Append method of the Response TextEdit, since some threads could call the method in question at the same time ???
No, that is still fine. The connection between the thread object and the text edit is a Qt::AutoConnection, so it detects that sender and receiver are two different threads.
Cheers,
_
Re: Call function of object within Threads.
Hi, Anda Skoa and everyone.
How do I set the "vthrThread" thread array, defined by the real-time user, to go out of the local scope to its method and stay in the global scope of the class in question?
It works like this.
Code:
void MainWindow::on_cmdIniciar_clicked()
{
Int vnumCont = ui->cboNumVezes->currentText().toInt();
clsThrTask *vthrThread[vnumCont];
for(int vnumIni=0; vnumIni < vnumCont; vnumIni++)
{
vthrThread[vnumIni] = new clsThrTask(vstrIdThread,this);
QObject::connect(vthrThread
[vnumIni
],
SIGNAL(sigRetorno
(QString)),ui
->txtResultado,
SLOT(append
(QString)));
....
I have tried it and it does not work.
Code:
(*.h)
Private:
Int vnumCont;
clsThrTask *vthrThread[];
(*.cpp)
void MainWindow::on_cmdIniciar_clicked()
{
for(int vnumIni=0; vnumIni < vnumCont; vnumIni++)
{
vthrThread[vnumIni] = new clsThrTask(vstrIdThread,this);
QObject::connect(vthrThread
[vnumIni
],
SIGNAL(sigRetorno
(QString)),ui
->txtResultado,
SLOT(append
(QString)));
// Erro Here "SIGSEGV" ....
void MainWindow::on_cmdParar_clicked()
{
for(int vnumIni=0; vnumIni < vnumCont; vnumIni++)
{
vthrThread[vnumIni].terminate();
Could you show me the correct form please?
Oops: Sorry for my lack of education, Thanks for the previous explanation.
Thanks.
Re: Call function of object within Threads.
See the suggestion to use a container, e.g. a vector/QVector
An array member would need to be a pointer to pointers, less obvious.
And don't call QThread::terminate(), that is almost always a bad idea.
Since your thread payload is event loop based, calling quit() should work.
Cheers,
_
Re: Call function of object within Threads.
Hi, Anda Skoa and everyone
On the Terminate () method, thanks for alerting me I took a look at QT Documentation.
Now on QVector, I'm reviewing the QT Documentation but I have no idea how to declare this class and start its constructor.
For simple examples I understood how to use it.
Any code examples to help?
Thanks.
Added after 16 minutes:
And before anyone says "You need to go back to your C ++ books and learn about variables and scoping. Your problem has nothing to do with everything and with basic C ++." I'm already doing this. :):):) :confused:
Re: Call function of object within Threads.
Hi, everyone.
Thanks, d_stranz.
I made the following change.
Code:
In (* .h) I will declare.
In (* .cpp) I did:
User informs the amount of threads through "vnumCont".
VthrThread-> resize (vnumCont);
And how will you stay here?
For (int vnumIni = 0; vnumIni <vnumCont; vnumIni ++)
{
VthrThread [vnumIni] = new clsThrTask (vstrIdThread, this); // ???? Erro Here.
QObject :: connect (vthrThread
[vnumIni
],
SIGNAL (sigRetorno
(QString)), ui
-> txtResult,
SLOT (append
(QString));
// ???? Erro Here.
Someone to help with the code ??
Thanks.
Re: Call function of object within Threads.
Almost
Code:
QVector<clsThrTask*> vthrThread;
A vector to pointers of your thread class
Cheers,
_
1 Attachment(s)
Re: Call function of object within Threads.
Hello everyone.
I hope this little QT project on parallel processing will be the starting foot tip for many like me, beginners in C ++ and QT Framework.
In this project we use some concepts about Threads (QThread), Processes (QProcess) and Vectors (QVector).
I want to register a special thanks to Anda Skoa, D_Stranz and Edr567, without them it would not be possible to end this case study.
I hope to count on you some other time.
Thanks, Thanks and Thanks.
The project will be available for download at the end of the post. :D:D