How to implement network thread in qt - multithreading

I am new to qt.
I have an application with one thread that uses libevent loop. I wanted to add another network thread that sends out jobs as post requests via QNetworkAccessManager.
How can i implemet it?
Suppose ,
1. i have Obj that inherts QOBject (Inside i have QnetworkAccessmanager that sends requests)
2. My Thread class that inherits QThread and reimplements run method with its event loop
I wanted to send new jobs(requests) to the event loop of this MyThread how do i do that?
Thanks in advance for answering.

Related

Qt "no matching function for call to connect", modifying Qt Fortune Threaded Server example

I am trying to modify the Qt Fortune Threaded Server example to read text from the connection and then echo it back. I defined tcpSocket in my FortuneThread.h file as follows:
QTcpSocket tcpSocket;
My new run function for the thread looks as follows:
void FortuneThread::run()
{
if (!tcpSocket.setSocketDescriptor(socketDescriptor)) {
emit error(tcpSocket.error());
return;
}
connect(&tcpSocket, SIGNAL(readyREAD()), this, SLOT(readCommand()) );
}
Which compiles and runs, but once I connect I get this error (referring to the connect line):
QObject: Cannot create children for a parent that is in a different thread.
(Parent is QTcpSocket(0x1eeb920), parent's thread is QThread(0x1bb3f90), current thread is FortuneThread(0x1eeb8f0)
QObject::connect: No such signal QTcpSocket::readyREAD() in ../fortune/fortunethread.cpp:60
Can someone explain the cause to me? Since tcpSocket is defined inside the FortuneThread class (which is run as a separate thread), and "this" refers to FortuneThread, I assume both objects are inside the thread? How to fix this?
Your socket object has been created in the main thread, but you're accessing it from a different thread. You need to create it inside of the thread's run() method. The location where the socket is defined doesn't matter. It will be created from the main thread when the C++ runtime library is doing static object initialization.
QTcpSocket * tcpSocket;
...
void FortuneThread::run() {
tcpSocket = new QTcpSocket;
...
}
I agree with Kuba Ober. You should read that great guide about Qt threads, objects and events. In particular, section called Signals and slots across threads. Authors recommends split controller and work parts into different essences.
Second issue in your code — case sensitive signal name. Change it to readyRead.
A problem with the Qt Fortune Threaded Server example is the way in which it uses threads. As the developers of Qt say, "You're doing it wrong"
The issue is the inheritance of QThread. The QThread class is not actually a thread, but a thread controller class and the only reason to inherit this, is if you want to change the behaviour of controlling threads.
The problem you're seeing is due to thread affinity; which thread an object belongs to.
If a thread is inherited like this: -
class FortuneThread : public QThread
{
Q_OBJECT
private:
QTcpSocket tcpSocket;
};
An object of FortuneThread is then instantiated from the main thread: -
FortuneThread* ft = new FortuneThread(parent);
The thread affinity for the thread and the objects it has instantiated (tcpSocket) is now the main thread, so the tcpSocket is running on the main thread, which is what the error is stating. At the point the run function is called, the connect is coming from the FortuneThread, but the tcpSocket is on the main thread.
The better way to solve this is to create your class, derived from QObject and move it to the thread: -
// Inherit from QObject, not QThread
class FortuneSocket : public QObject
{
Q_OBJECT
public slots:
void Run();
private:
QTcpSocket tcpSocket;
};
QThread* pThread = new QThread(parent);
FortuneSocket* pFortune = new FortuneSocket(parent);
connect(pThread, &QThread::started, pFortune, &FortuneSocket::Run); // Qt5 connect style
// move the fortune socket to the thread: -
pFortune->moveToThread(pThread);
Now, when you start the thread with pThread->start(), the FortuneSocket object and all of its members are running on the new thread.
Using threads this way also means that you can move multiple objects to a single thread, rather than having one object per thread. Note that creating more threads than CPU cores is pointless!
Finally, there's a more in-depth article on how to use QThread, here.

QThread: Call child thread method from main thread

I have a thread created by inheriting QThread in which I called exec() to initiate the event loop. And this class that inherits QThread has a method in it.
How can I call that method from the main thread for it to execute in the child thread?
I assume that the execution of that method has to be queued in the child thread's event loop, so calling threadObject->childThreadMethod() won't be a good idea.
Is there any solution to this?
You can not call every member functions of the thread, but only slots and Q_INVOKABLE methods.
Use QMetaObject::invokeMethod() to call such a method, and make sure to set the connection type to Qt::QueuedConnection.
That way, the method will be called in the second thread whenever the control returns to the event loop in the second thread. The caller, i.e. the main thread, will continue immediately, so you won't be able to get a return value from the called method.
Behind the scenes, QMetaObject::invokeMethod adds a MetaCallEvent to the second thread's event queue.
Alternatively, create a signal/slot connection, and then emit a signal whenever you want the slot to be called in the other thread.
to run some function in a separate thread you can use QtConcurrent::run (i use it with QFutureWatcher). To run it every 5 or so seconds, use QElapsedTimer class
QFuture<void> future = QtConcurrent::run(this, &MyClass::foo2, ...foo2 arguments);
http://qt-project.org/doc/qt-4.8/qtconcurrentrun.html#run or check it here https://stackoverflow.com/search?q=QtConcurrent%3A%3Arun
or you can subclass QThread, reimplement QThread::run() method with the stuff you want to happen in your thread, and then create an instance of your thread and call start() on it.

Form gets freezed during loading data in a seperate thread

I use TIdHTTP component to load xml data from a bank in a seperate thread but my form is getting freezed during that time...
what could be the problem ?
I have a main form and thread class, in thread class i have a method called loadData and on thread::Execute i Synchronize(loadData);
when button gets clicked I created the instance of thread class like testThread *t=new testThread(false);
and that's all
when i click the button the main form freezes?
even seperate thread didn't help????
Please help!!!
Synchronize() is running your loadData() method in the context of the main thread, not in the context of your worker thread. That is why your main thread blocks while loadData() is busy. You are misusing Synchronize(), rendering your thread useless. You need to do the bulk of your thread work outside of Synchronize(), and then use Synchronize() only to perform small updates in the main thread when needed, like displaying status (even then, Synchronize() is not always the best choice for that).

Creating a QThread event loop in an existing non QT thread

My code is a plugin of a host software which gets limited processing time. Therefore, I create a second thread (via system API) and start QApplication there. That way, the GUI runs smoothly.
Now, I would like to run a QThread event loop in the original such that I could use Signal/Slot (Qt::QueuedConnection) to invoke functions that are not thread safe in the host software.
Is there a way to create such QThread event loop without creating a new thread?
Thanks!
I'm not quit sure if i get you right,
but you can start your own event loop just by calling QEventLoop::exec() on a e.g. private class member.
Don't forget to call QEventLoop.exit().
Bye, Lars

Basic QT Event handling / Threading questions?

Greetings ,
I am new to QT (4.6) and have some basic questions regarding its event mechanism.I come from Swing background so I am trying to compare it with QT.
1) Does Event-processing-loop run in seperate thread? (like EventDispatch thread in Swing) ?
2) If we open several 'QMainWindow' do they run in several threads?
3) Whats the best way to run an intensive process in a seperate thread? (like SwingWorker in Swing ? )
4) If intesive-process runs in a seperate thread ,is it possible to call UI methods like update(),repaint() from that process?
thanks in advance.
1 Event loop running in the same thread
2 All UI elements are living in the same thread the one in which your main() function executed.
3 There are QThread class which allows you to have a thread with separate event loop. There is QRunable abstract class to be able to run repeating long running tasks in separate threads using QThreadPool.
4 update() and repaint() are slots and the best way to call them from separate thread is to use queued connection with a signal in your object which lives in separate thread (read QObject::connect documentation anbout connection types)
You can find all necessary information by reading documentation of classes I've mentioned.

Resources