I want to ask a question about Application architecture1. There will be the main GUI thread for providing user interaction2. A Receive thread based on UDP socket that will receive UDP packets as they arrive (want this to be blocking.3. Another thread for sending event based as well as periodic UDP packets.How do I implement this architecture in Qt, basically i have following questions:1. For the Receive Thread, how do I make it blocking ?I know about readyRead() signal, and I can connect it to some slot that will process the datagram, but how do i loop this so that this thread does this forever. 2. In send Thread I can generate a signal form the GUI thread which will be received by the Sending Thread and a slot here will write some data on the socket, but again how will this thread survive when it has nothing to send, I mean loop, poll over something what ?
Use event loops in the secondary threads.
QThread::exec() starts the thread's event loop which will run until QThread::quit() is called. That should solve your "how to wait until something happens" problem. The default implementation of QThread::run() just calls exec(), so I'd go with that. You could set everything up in your main() method, e.g. for the sender thread:
//Create UI
MainWindow mainWindow;
mainWindow.show();
//set up sender thread and the `QObject` doing the actual work (Sender)
QThread senderThread;
Sender sender; //the object doing the actual sending
sender.moveToThread(&sender); //move sender to its thread
senderThread.start(); //starts the thread which will then enter the event loop
//connect UI to sender thread
QObject::connect(&mainWindow, SIGNAL(sendMessage(QString)), &sender, SLOT(sendMessage(QString)), Qt::QueuedConnection);
...
const int ret = app.exec(); // enter main event loop
`senderThread.quit();` //tell sender thread to quit its event loop
`senderThread.wait();` //wait until senderThread is done
`return ret;` // leave main
Sender would just be a QObject with a sendMessage() slot doing the sending, a QTimer plus another slot for the periodic UDP packages, etc.
Related
I have a process ProcessA that starts 2 threads ThreadA and ThreadB. Both threads send and recv data from ProcessB using the same socket descriptor.
So essentially:
int s;
void thread_fnA(void*)
{
while(1) {
sendto(s);
recvfrom(s);
}
}
void thread_fnB(void*)
{
while(1) {
sendto(s);
recvfrom(s);
}
}
int main()
{
s = socket(AF_UNIX, SOCK_DGRAM, 0);
bind(s);
dispatch_thread(A);
dispatch_thread(B);
}
Is there a possibility that the message to be received by thread B could be received in thread A.
So sequence of events:
Thread A prepares a message and calls sendto();
Thread B starts executing and prepares a message and calls sendto();
Thread B calls recvfrom() simultaneously with Thread A.
However the message content expected by both threads are different.
Can the messages be exchanged, ThreadB destined message be received by ThreadA.
Should the send and receive be involved in some locks. (Mutex)
I would suggest another design, in where you have a single thread doing the sending and receiving, and message queues for the other threads.
When the send/receive thread receives a message it check what kind of message it is, and ad it to the (protected) queue of the correct processing thread. The processing threads (your current treads A and B) gets the messages from its respective message queue, and process the messages in any way it pleases. Then if thread A or B wants to send a message, it passes it to the send/receive thread using another queue, which the send/receive thread polls.
Alternatively, the processing threads (A and B in your example) could send directly over the socket. Or each have a different socket used only for sending.
Since you are using the same socket in both threads it is possible that one thread reads the message that is destined to the other thread. Even if you use mutex, the design would be very difficult. You can open two sockets (or even pipes):
One socket is for communication in the direction A->B
The second socket in the direction B->A
A second possibility is having one socket with one writer (thread A) and one reader (thread B). The reader, when it receives a datagram, it decides, maybe based on datagram payload, what task to do. Or it can also send a task to other set of workers that will process the datagram.
I need to transmit Strings to Main thread (there is GUI) to add them to javafx' TextFlow.
In the background thread's run(), reader waits strings from JSch channel. On new stings it must transmit them to main thread. So main thread can't wait data from background thread (as it is GUI thread), and background thread must send some event with new Strings.
Another trouble, that in application can be, for example, 4 background threads, that reads some data from JSch channel and send it to one window to show.
To transmit data to the GUI thread,use Platfotm.runLater() method
Platform.runLater(() -> {
/*send your data from here*/
});
Platform.runLater makes you modify the GUI thread from other threads, It has a swing equivalent of SwingUtilities.invokeLater
I have a thread with a TCP Socket that connects to a server and waits for data in a while loop, so the thread never ends. When the socket receives data, it is parsed, and based on the opcode of the packet, should call x function. Whats the fastest/best way to go about that?
I read around that doing some kind of task/message queue system is a way of doing it, but not sure if there is any better options.
Should mention that I can not use boost:
Edit: Sorry, half asleep haha.
Here is the loop from thread x:
while (Running)
{
if (client.IsConnected())
{
Recieve();
}
FPlatformProcess::Sleep(0.01);
}
In the Receive function, it parses the data, and based on the packet opcode, I need to be able to call a function on the main thread (the GUI thread), because a lot of the packets are to spawn GUI objects, and I can't create GUI objects from any other thread than the main one.
So basically: I have a main thread, that spawns a new thread that enters a loop, listens for data, and I need to be able to call a function from the 2nd thread that runs on the main thread.
I have a condition where I have unknown amount of 3rd party threads calling a callback in my application. That callback emits a signal in the context of the threads that called it. Always the same signal, but 10 different threads can emit it at any given moment.
I'd like to queue all of those singlas and process them with the appropriate slot in the context of a single QThread I own.
How do I do that? The following code does not work. Although I see it signals being emitted, from different threads, my "On..." is never called.
QObject::connect(this,SIGNAL(ProcessQueuedOutEvent(int)),
this,
SLOT(OnProcessQueuedOutEvent(int)),
Qt::QueuedConnection);
Does your QThread run the event loop? It has to do it to receive signals:
Queued Connection The slot is invoked when control returns to the
event loop of the receiver's thread. The slot is executed in the
receiver's thread.
Basically queued connection works the following way:
The originator issues a signal.
Qt creates an event and posts it into the receiver event queue.
The receiver goes through its event queue, picks up the events and dispatches the signals into the connected slots.
Hence if you do not run the event queue, the signals are posted but your thread will never receive them.
So basically your thread should do some initialization in run() but then call exec() and pass it to Qt.
If your thread also needs to run some periodic operations besides checking for signals, you can do that by using QTimer::singleShot timers posting signals to the same thread.
See http://qt-project.org/doc/qt-4.8/threads-qobject.html#signals-and-slots-across-threads
PS. If you pass the pointers via queued connections, the pointer must be valid until the signal is processed, which may be after your function which posted the signal existed. A common error is to post signals with strings as a parameters which are stored in a local char[] buffer. At the moment the buffer is accessed the original function is finished, and the string is already gone. Those errors depend on thread scheduling and therefore hard to debug. If you pass the pointers via queued connection, they must be heap-allocated and the callee must be responsible to free them.
If I understand your problem correctly, you have a callback function executed by many threads. This callback function should emit a signal connected to a slot in a object which is in another thread.
What I suggest is to create a threaded receiver object, using the pattern (moveToThread). Then using the postEvent method to a private implementation method. The call is thread safe (the parameter is copied).
So your callbacks can directly and safely call:
OnProcessQueuedOutEvent
which posts an event to the QThread event loop.
Receiver.h
class Receiver : public QObject
{
Q_OBJECT
public:
explicit Receiver( QObject* parent = 0 );
virtual ~Receiver();
public slots:
void OnProcessQueuedOutEvent( int val );
private slots:
void OnProcessQueuedOutEventImpl( int val );
private:
QThread m_thread;
};
Receiver.cpp
Receiver::Receiver( QObject* parent )
: QObject(parent)
{
moveToThread(&m_thread);
m_thread.start();
}
Receiver::~Receiver()
{
// Gracefull thread termination (queued in exec loop)
if( m_thread.isRunning() ) {
m_thread.quit();
m_thread.wait();
}
}
void OnProcessQueuedOutEvent( int val )
{
QMetaObject::invokeMethod(this, "OnProcessQueuedOutEventImpl", Q_ARG(int,val));
}
void OnProcessQueuedOutEventImpl( int val )
{
// do stuff here
}
I have a main program that creates the threads in order:
ThreadB then
ThreadA (which is passed ThreadB's ID)
using the CreateThread function.
Thread A sends a message to Thread B using PostThreadMessage.
B gets the message using GetMessage.
The problem I am having is that PostThreadMessage blocks randomly the first time it is called and never returns, some times the program funs fine, other times I run the program and it blocks with 0 CPU usage at the first postthreadmessage. However if I add Sleep(10) to ThreadA before the first PostThreadMessage, I never seem to encouter this problem.
What am I missing about the timing of threads and messages?
You cannot send a message to a thread until it has a message queue. Message queues are not created until that thread calls a function such as GetMessage or PeekMessage. What your sleep does is delay the sending thread long enough that the receiving thread has called GetMessage and set up its message queue.
Incidentally, I strongly recommend against using PostThreadMessage as the messages can get lost. It is better to create a message-only window (with a parent of HWND_MESSAGE) on the receiving thread and send messages to that instead.
To add to Anthony Williams correct answer, the code I use to deal with this looks like. I have a class similar to MyThread...
void MyThread::Start()
{
m_hResumeMain = CreateEvent(NULL,FALSE,FALSE,NULL);
m_hThread = CreateThread(NULL,0,ThreadProc,this,0,&m_dwThreadId);
WaitForSingleObject(m_hResumeMain,INFINITE);
CloseHandle(m_hResumeMain);
m_hResumeMain=0;
}
DWORD MyThread::ThreadProc(LPVOID pv)
{
MyThread* self = (MyThread*)pv;
return self->ThreadProc();
}
DWORD MyThread::ThreadProc()
{
MSG msg;
// Create the thread message queue
PeekMessage(&msg,0,0,0,PM_NOREMOVE);
// Resume the main thread
SetEvent(m_hResumeMain);
while(GetMessage(&msg,0,0,0)>0){
if(msg.hwnd){
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else {
DoThreadMessage(&msg);
}
}
return 0;
}
The crux of the issue is you ultimately cannot rely on a Sleep to guarantee that the worker thread is sufficiently initialized. Plus, in general there is usually some mimimal amount of work a worker thread needs to have done before the launching thread should be allowed to resume. So create an event object before creating the thread, wait for it on the main thread and signal it on the worker thread once the initialization is done.