Communication with QThread not working with Signals / Slots - c++

I followed this tutorial for QThreads:
http://mayaposch.wordpress.com/2011/11/01/how-to-really-truly-use-qthreads-the-full-explanation/
The only problem I am having is killing the QThread. I have a flag in the process() loop of the worker object that I push into my QThread instance that is called m_ShouldSendFrames. If that flag is flipped to false, then my processing loop breaks and the worker object emits the finished() signal.
The problem I have is that I cannot seem to get my worker object in the QThread to receive my stopSendingFrames() signal from the main thread. I connect that ( and the connection returns 'true' ) like this:
connect(this, SIGNAL(stopSendingFrames()), m_UdpWorkerBlended, SLOT(stopFrames()),Qt::QueuedConnection); // Stop broadcasting
In my killUdpThread function, I'd like to emit the stopSendingFrames() signal and have the m_UdpWorker object get it. But it never does! The only way I can get that flag to change is to do this in the killUdpThread:
m_UdpWorkerBlended->stopFrames();
That however, is unsafe and randomly crashed because it is not called from the QThread that the worker is running in.
I've also tried the invokeMethod way - but it never fires the slot either:
QMetaObject::invokeMethod(m_UdpWorkerBlended,"stopFrames",Qt::QueuedConnection);
Can someone please help me understand why I cannot call invokeMethod or use signals to fire my slot running in the worker object in the QThread but I can call it ( unsafely ) directly? Thanks!
Start thread function:
int UdpThreadController::startUdpThread(int frameType, int port, QString ip) {
#if SINGLETON_CAMERA_UDP_DEBUG
qDebug() << "Starting Thread! Frame type is: " << frameType;
#endif
// Check for type of frame to emit
if ( frameType == 0 ) {
#if SINGLETON_CAMERA_UDP_DEBUG
qDebug() << "Frames are vl";
#endif
// Delete any existing threads / workers
killUdpThread(0);
// New objects
m_UdpThreadBlended = new QThread();
m_UdpWorkerBlended = new UdpWorker();
// Assign Port and IP and Frame Type
m_UdpWorkerBlended->m_ShouldSendFrames = true;
m_UdpWorkerBlended->m_Port = port;
m_UdpWorkerBlended->m_AddressToUse = ip;
m_UdpWorkerBlended->m_FrameType = frameType;
// Push into thread
m_UdpWorkerBlended->moveToThread(m_UdpThreadBlended);
// Connect signals
connect(this, SIGNAL(stopSendingFrames()), m_UdpWorkerBlended, SLOT(stopFrames()),Qt::QueuedConnection); // Stop broadcasting
connect(m_UdpThreadBlended, SIGNAL(started()), m_UdpWorkerBlended, SLOT(process()));
connect(m_UdpWorkerBlended, SIGNAL(finished()), m_UdpThreadBlended, SLOT(quit()));
connect(m_UdpWorkerBlended, SIGNAL(finished()), m_UdpWorkerBlended, SLOT(deleteLater()));
connect(m_UdpThreadBlended, SIGNAL(finished()), m_UdpThreadBlended, SLOT(deleteLater()));
m_UdpThreadBlended->start();
// All done
return 0;
Kill thread function:
int UdpThreadController::killUdpThread(int frameType) {
#if SINGLETON_CAMERA_UDP_DEBUG
qDebug() << "Killing Thread! Frame type is: " << frameType;
#endif
// Check for type of frame to emit
if ( frameType == 0 ) {
// Delete any existing threads / workers
if ( m_UdpWorkerBlended ) {
#if SINGLETON_CAMERA_UDP_DEBUG
qDebug() << "Emit signal to kill thread...";
#endif
// Stop broadcasting
m_UdpWorkerBlended->stopFrames();
}
#if SINGLETON_CAMERA_UDP_DEBUG
qDebug() << "Success ending UDP...";
#endif
// All done
return 0;
}

Thanks for the input. I solved it by having a singleton that has a flag that the processing loop in my worker object in the QThread reads each loop iteration. It is protected by a QReadWrite lock.
int UdpThreadController::killUdpThread(int frameType) {
#if SINGLETON_CAMERA_UDP_DEBUG
qDebug() << "Killing Thread! Frame type is: " << frameType;
#endif
// Check for type of frame to emit
if ( frameType == 0 ) {
// Delete any existing threads / workers
if ( m_UdpWorkerBlended ) {
#if SINGLETON_CAMERA_UDP_DEBUG
qDebug() << "Setting flag to kill thread...";
#endif
// Stop broadcasting
m_Lock.lockForWrite();
m_ShouldSendFramesBlended = false;
m_Lock.unlock();
}
#if SINGLETON_CAMERA_UDP_DEBUG
qDebug() << "Success ending Blended UDP...";
#endif
// All done
return 0;
bool UdpThreadController::shouldContinueSendingFrames(int frameType) {
#if SINGLETON_CAMERA_UDP_DEBUG
qDebug() << "Checking if we should continue processing: " << frameType;
#endif
// Check for type of frame to emit
if ( frameType == 0 ) {
m_Lock.lockForRead();
#if SINGLETON_CAMERA_UDP_DEBUG
qDebug() << "Should continue Blended: " << m_ShouldSendFramesBlended;
#endif
bool shouldBroadcast = m_ShouldSendFramesBlended;
m_Lock.unlock();
// All done
return shouldBroadcast;
}

Related

Why can't I start a QThread on a signal?

I want to start a QThread when another one starts, but it doesn't work.
main.cpp snippet
Worker stat_worker;
stat_worker.moveToThread(stat_worker.stat_thread);
Worker some;
some.moveToThread(some.somethread);
QObject::connect(stat_worker.stat_thread, SIGNAL(started()), some.somethread, SLOT(start()));
QObject::connect(some.somethread, SIGNAL(started()), &some, SLOT(print_some()));
stat_worker.stat_thread->start();
worker.h
class Worker : public QObject
{
Q_OBJECT
public:
explicit Worker();
QThread *stat_thread = new QThread;
QThread *somethread = new QThread;
signals:
//some signals
void start_thread();
public slots:
//some slots
void print_some();
void somethread_starter();
};
#endif // WORKER_H
worker.cpp related function
void Worker::print_some()
{
qInfo() << "-somethread started() signal arrived!";
}
When I tried starting a thread with clicking a pushbutton it didn't work either.
Even creating a slot which starts the thread:
QObject::connect(stat_worker.stat_thread, &QThread::started, &some, &Worker::somethread_starter);
void Worker::somethread_starter()
{
qInfo() << "-I got started by another thread!";
somethread->start();
}
or a signal that is emitted on starting the other thread:
void Worker::wip_status(){
emit start_thread();
}
QObject::connect(stat_worker.stat_thread, &QThread::started, &stat_worker, &Worker::wip_status);
QObject::connect(&stat_worker, &Worker::start_thread, &some, &Worker::somethread_starter);
work.
Thanks in advance for replying to my post.
I tried to reproduce OPs issue with my own MCVE (which is just a bit shorter).
#include <QtWidgets>
struct Worker: QObject {
QString name;
QThread qThread;
Worker(const QString &name): name(name)
{
moveToThread(&qThread);
connect(&qThread, &QThread::finished, this, &Worker::reportFinished);
}
void start()
{
qDebug() << "Start" << name;
qThread.start();
}
void reportFinished()
{
qDebug() << "Exit" << name;
}
};
// main application
int main(int argc, char **argv)
{
qDebug() << "Qt Version:" << QT_VERSION_STR;
QCoreApplication app(argc, argv);
Worker worker1("worker 1");
Worker worker2("worker 2");
// install signal handlers
QObject::connect(&worker1.qThread, &QThread::started, &worker2, &Worker::start);
worker1.start();
// runtime loop
return app.exec();
}
Output:
Qt Version: 5.13.0
Start "worker 1"
This what OP observed. So, what?
the worker1.qThread.started signal is connected to the worker2.start slot
the worker1 is started
worker2 doesn't seem to start.
What made me suspicious: moveToThread().
The intention is to associate the Worker object with its member QThread.
What I'm not sure about: Is this possible before the QThread is started?
To check this out, I commented the moveToThread():
Worker(const QString &name): name(name)
{
//moveToThread(&qThread);
connect(&qThread, &QThread::finished, this, &Worker::reportFinished);
}
Output:
Qt Version: 5.13.0
Start "worker 1"
Start "worker 2"
The reason why I commented the moveToThread():
The call of qThread::start() should happen in the context of the main application (thread).
So, moving worker2 to its QThread means that the signal is sent to the event loop of worker2.qThread – which is actually not yet started.
Hence, the event cannot be processed.
The moveToThread() should be done later – e.g. in reaction of the started() signal:
#include <QtWidgets>
struct Worker: QObject {
QString name;
QThread qThread;
Worker(const QString &name): name(name)
{
connect(&qThread, &QThread::started, this, &Worker::moveThisToThread);
connect(&qThread, &QThread::finished, this, &Worker::reportFinished);
}
void start()
{
qDebug() << "Start" << name;
qThread.start();
}
void moveThisToThread()
{
moveToThread(&qThread);
qDebug() << name << "associated to its thread, from now.";
}
void reportFinished()
{
qDebug() << "Exit" << name;
}
};
// main application
int main(int argc, char **argv)
{
qDebug() << "Qt Version:" << QT_VERSION_STR;
QCoreApplication app(argc, argv);
Worker worker1("worker 1");
Worker worker2("worker 2");
// install signal handlers
QObject::connect(&worker1.qThread, &QThread::started, &worker2, &Worker::start);
worker1.start();
// runtime loop
return app.exec();
}
Output:
Qt Version: 5.13.0
Start "worker 1"
"worker 1" associated to its thread, from now.
Start "worker 2"
"worker 2" associated to its thread, from now.
Bonus Question:
So does that mean "QThread::start" is useless as receiver of a signal?
No, it's not. Even if there is no existing signal with that signature (I know about) the application developer is free to “invent” one.
However, remembering that Qt5 doesn't actually require explicitly marked SLOTs to use them for signals, a more obvious answer may be found in the past:
With Qt4 signals, the QThread::start slot could have been connected to the QThread::started signal directly. (The default value of the one and only parameter in QThread::start becomes effective then.)
As I have no experience with Qt4 signals (I started with Qt5), I modified my sample code to prove me right:
QObject::connect(&worker1.qThread, SIGNAL(started()), &worker2.qThread, SLOT(start()));
Output:
Qt Version: 5.13.0
Start "worker 1"
"worker 1" associated to its thread, from now.
"worker 2" associated to its thread, from now.
The Start "worker 2" isn't emitted anymore as worker1.started() calls worker2.qThread.start() directly, now.
So, with Qt4 signals the original code of OP might have been worked.
It wasn't the incompatibility of signal and slot (as somebody guessed) which caused the issue but probably the above described moveToThread() issue (as well) which didn't make it work satisfyingly.

Qt QTcpSocket() readReady Signal never fires (slot never called) in multithreaded Server applicaton. waitForReadyRead() method works fine

I'm writing a threaded TcpServer (each client in its own thread) using QTcpServer and QTcpSocket. The client application works correctly and sends data every 3 seconds but the readReady() signal never fires, meaning my receive_data() function is never called. When using socket->waitForReadyRead() and calling receive_data() by myself everything works fine. Please have a look at the code below, maybe I made some mistake with the moveToThread / connect functionality Qt offers.
Client.h
#ifndef CLIENT_H
#define CLIENT_H
#include <QThread>
#include <QTcpSocket>
#include <QHostAddress>
#include "PacketDefinitions.h"
#include "tcpserver.h"
class Client : public QObject
{
Q_OBJECT
public:
explicit Client(int socket,TcpServer *parent,bool auto_disconnect = true);
~Client();
bool isGameServer(){return is_gameserver;}
GameServerPacket getGameServerData(){return gameserver;}
void run();
private:
QTcpSocket* client;
TcpServer *parent_server;
int socket;
GameServerPacket gameserver;
ClientPacket clientdata;
bool is_gameserver;
bool auto_disconnect;
QHostAddress client_ip;
quint16 client_port;
signals:
void disconnected(Client *);
private slots:
void remove_from_clientlist();
void receive_data();
void display_error(QAbstractSocket::SocketError error);
};
#endif // CLIENT_H
Client.cpp
#include "client.h"
#include "PacketDefinitions.h"
#include "time.h"
#include <iostream>
Client::Client(int _socket, TcpServer *parent,bool _auto_disconnect)
{
auto_disconnect = _auto_disconnect;
parent_server = parent;
is_gameserver = false;
socket = _socket;
}
void Client::run(){
client = new QTcpSocket();
if(client->setSocketDescriptor(socket) == false){
std::cout << client->errorString().toStdString() << std::endl;
remove_from_clientlist();
return;
}
connect(client,SIGNAL(disconnected()),this,SLOT(remove_from_clientlist()));
if(connect(client,SIGNAL(readyRead()),this,SLOT(receive_data()),Qt::DirectConnection) == false) return;
connect(client,SIGNAL(error(QAbstractSocket::SocketError)),this,SLOT(display_error(QAbstractSocket::SocketError)));
client_ip = client->peerAddress();
client_port = client->peerPort();
std::cout << "New incomming connection " << client->peerAddress().toString().toStdString() << ":" << client->peerPort() << std::endl;
//this works fine
// while(client->waitForReadyRead()){
// receive_data();
// }
}
void Client::receive_data(){
QDataStream stream(client);
stream.setVersion(QDataStream::Qt_5_2);
quint32 magic; stream >> magic;
//interpret data
if(magic == GAMESERVER_MAGIC){
is_gameserver = true;
gameserver.Read(stream);
gameserver.port = client_port;
gameserver.ip = client_ip;
time(&(gameserver.last_update));
parent_server->add_server(gameserver.ip.toString(),gameserver);
std::cout << "GameServer " << gameserver.name << " registerd" << std::endl;
}else if(magic == CLIENT_MAGIC){
is_gameserver = false;
clientdata.Read(stream);
//get nearby servers
GameServerListPacket server_list = parent_server->getServerList(clientdata);
QDataStream outstream(client);
server_list.Write(outstream);
std::cout << "Sending ServerList(" << server_list.server_count << ") to " << client->peerAddress().toString().toStdString() << std::endl;
if(auto_disconnect){
//client->flush();
client->waitForBytesWritten();
}
}else{
std::cout << "Unknown package " << magic << std::endl;
}
//not enough data read, somthing is wrong, just for debugging
if(client->bytesAvailable()> 0) std::cout << "BytesAvailable " << client->bytesAvailable() << std::endl;
if(auto_disconnect) remove_from_clientlist();//close the connection once the serverlist was deployed
}
In the TcpServer.cpp add_client() is called when newConnection() was emitted by the QTcpServer:
void TcpServer::add_client(){
while(server->hasPendingConnections()){
QTcpSocket *socket = 0;
if(thread_pool.size() < max_connections && (socket = server->nextPendingConnection())){
QThread *thread = new QThread();
Client * client = new Client(socket->socketDescriptor(),this,auto_disconnect);
client->moveToThread(thread);
client->run();
thread->start();
connect(client,SIGNAL(disconnected(Client*)),this,SLOT(remove_client(Client*)));
WRITELOCK(thread_pool.insert(client,thread));
}
}
}
the order calling client->run() and thread->start() doesn't seem to matter. Some time ago the code (not this exact code) worked fine but I can't remember what I changed that made it fail. Any help is appreciated!
Thanks in advance
Fabian
Edit 1:
I derived from QTcpServer and reimplemented void incomingConnection(qintptr socketDescriptor) which works fine. I dont use QThreadPool, its just a QMap and remove_client(Client*) closes the QTcpSocket and stops the thread and removes it from the map. Everything works fine on linux, on windows I get the following error: QSocketNotifier: socket notifiers cannot be disabled from another thread ASSERT failure in QCoreApplication::sendEvent: "Cannot send events to objects owned by a different thread....
Caused by this remove_client(Client*)
void TcpServer::remove_client(Client *client){
//disconnect(client,SIGNAL(disconnected(Client*)),this,SLOT(remove_client(Client*)));
lock.lockForWrite();
QMap<Client*,QThread*>::iterator itr = thread_pool.find(client);
if(itr != thread_pool.end()){
//delete itr.key(); causes the problem on windows
itr.value()->quit();
itr.value()->wait();
delete itr.value();
thread_pool.erase(itr);
}
lock.unlock();
}
Where and how should I free the Client object? If i'd use QThreadPool theres no way to iterate through the clients in case i want to send a message to more than one client. I could use a list/map holding only the Client* but then QThreadPool might delete them for me right before i want to access it. Any suggestions?
There is a problem with how you move your client object to a new thread. Actually, Client::run executes in the same thread as TcpServer::add_client.
Also QTcpSocket client remains in the default thread, while its container (Client class) is moved to a new thread. That's why the connection with Qt::DirectConnection type doesn't work.
Try this:
class Client : public QObject
{
Q_OBJECT
...
public slots:
void run();
...
}
Client::Client(int _socket, TcpServer *parent,bool _auto_disconnect)
{
...
client = new QTcpSocket(this);
}
void Client::run()
{
...
connect(client, SIGNAL(readyRead()), this, SLOT(receive_data()));
...
}
And here's how you should move your client to a new thread:
void TcpServer::add_client()
{
...
QThread *thread = new QThread();
Client * client = new Client(socket->socketDescriptor(),this,auto_disconnect);
client->moveToThread(thread);
connect(thread, SIGNAL(started()), client, SLOT(run()));
thread->start();
...
}
There are a number of things wrong with your code.
1.You have two QTcpSocket object trying to collect data from the same underlying socket descriptor. You appear to use the first one only to get access to the socket descriptor value which you then pass to your Client class. You might end up losing data because you won't be able to tell which socket will be getting what data from the operating system.
If you are creating a derived class of QTcpServer, rather reimplement QTcpServer::incomingConnection(qintptr socketDescriptor) instead of your existing TcpServer::add_client() function. Since this protected function is called once for every new connection, you don't need to make any connections to the newConnection() signal, nor do you have to loop while new connections are pending. You will also then only have one QTcpSocket connected to each socket descriptor so you won't lose data.
2.You seem to be using QThreadPool to manage threads. If you make Client a derived class of QRunnable (take not that with multiple inheritance of QObject, QObject must always be first), you don't need to check the maximum connections and you can eliminate all the QThread boiler-plating.
Taking 1. and 2. into account, your TcpServer::add_client() function will be replaced with:
void TcpServer::incomingConnection(qintptr socketDescriptor){
Client * client = new Client(socketDescriptor,this,auto_disconnect);
connect(client,SIGNAL(disconnected(Client*)),this,SLOT(remove_client(Client*)));
QThreadPool::globalInstance()->start(client);
}
With QThreadPool, there's no need to check whether the max number of threads has been reached or not. If the maximum has been reached, any new calls to start() will queue the next connection until a thread becomes available.
3.The reason your socket is not reading any data unless you call waitForReadyRead() is because you're executing the run() function in the main thread, creating the local socket in the main thread, you make a DirectConnection with the instance of Client and then move client to a different thread. You cannot have direct connections between threads.
You will need to add a local QEventLoop to your run() function to handle all events and signals of your new thread but remember to connect signals to your loop's quit() slot so the run() function will exit, otherwise your thread will continue to run forever.

QProcess does not complete creating file

I am just trying to create a file with QProcess by the following source code:
void Processmethod()
{
QDialog *ProcessMessage = new QDialog;
Ui::DialogProcessMessage Dialog;
Dialog.setupUi(ProcessMessage);
ProcessMessage->setModal(true);
ProcessMessage->setAttribute(Qt::WA_DeleteOnClose);
ProcessMessage->show();
processmethodONE();
}
void processmethodONE()
{
QString ProcessCommand = "w8 " + blablubli";
Prozess.setWorkingDirectory(Path); //QProcess "Prozess" is globaly defined
Prozess.setStandardOutputFile(Path); //in my class
Prozess.start(ProcessCommand);
QProcess::ExitStatus Status = Prozess.exitStatus();
if (Status == 0)
{
std::cout << "File created!" << std::endl;
}
}
This process creates out of another file which is located in the QString "Path" a new file, let me call it "PROFILE" (PRO for Problem :). The Profile also is created, but is never completed, I guess not even 50% of the file are completed.
Just when using
while(!Prozess.waitForFinished())
{
qApp->processEvents();
std::cerr << "Process Create PROFile running " << std::endl;
}
the file is written completely.
Furthermore I tried to use the QProcess finished(int) Signal to start another method and deleted the while loop (which freezes the whole GUI). I declared it in the constructor with:
connect(&Prozess, SIGNAL(finished(int)), this, (SLOT(processmethodTWO())));
But I guess this could not work because the first process isn't finished completely. Where is the problem?
There is no warranty that right after Prozess.start(ProcessCommand); process will be finished, so calling "Prozess.exitStatus();" right after it will give you "false positive". You certainly will have to wait until process is finished. You may either do it with with while loop, that you suggested or with QEventLoop
// ...
Prozess.setStandardOutputFile(Path); //in my class
QEventLoop loop;
connect(&Prozess, SIGNAL(error(QProcess::ProcessError)), &loop, SLOT(quit()));
connect(&Prozess, SIGNAL(finished(int, QProcess::ExitStatus)), &loop, SLOT(quit()));
Prozess.start();
loop.exec();
// Now your process status should be valid:
QProcess::ExitStatus Status = Prozess.exitStatus();

How to use a process (QProcess) in a new thread (QThread)?

I have the following code:
void Processmethod()
{
QDialog *ProcessMessage = new QDialog;
Ui::DialogProcessMessage Dialog;
Dialog.setupUi(ProcessMessage);
ProcessMessage->setModal(true);
ProcessMessage->setAttribute(Qt::WA_DeleteOnClose);
ProcessMessage->show();
qApp->processEvents();
processmethodONE();
processmethodTWO();
processmethodTHREE();
}
void processmethodONE()
{
QString ProcessCommand = "w8 " + blablubli";
Prozess.setWorkingDirectory(Path); //QProcess "Prozess" is globaly defined
Prozess.setStandardOutputFile(Path); //in my class
QThread* thread = new QThread;
Prozess.moveToThread(thread);
Prozess.start(ProcessCommand);
while(!Prozess.waitForFinished(2000))
{
std::cerr << "Process running " << std::endl;
}
QProcess::ExitStatus Status = Prozess.exitStatus();
if (Status == 0)
{
std::cout << "File created!" << std::endl;
}
}
In this source code I try to open a popup dialog before some processes are starting. problem is that the dialog is not clickable, but on the dialog I want to create a button to abort the running method. As you can see I tried using QThread to run the process(es) in another thread, but still I can't click the dialog. Furthermore if I open my application (GUI) with the "application/x-executable"-file the dialogs content is missing when activating the above shown method. How can I fix these problems? Where am I wrong? greetings
void processmethodONE()
{
QThread* thread = new QThread;
Prozess.moveToThread(thread);
Prozess.start(ProcessComand);
Here you moved the QProcess to another thread. But then you call start() on it. That's already not thread-safe.
while(!Prozess.waitForFinished(2000))
{
std::cerr << "Process running " << std::endl;
}
This blocks and makes using a thread useless. Also, it's not thread-safe.
You should instead not use threads but:
remove the waitForFinished() call
Connect the finished() and error() signals of the QProcess to slots which then start the next step, i.e. processMethodTWO.
I would also advise against reusing QProcess objects and just create a new one for each step.
While I still don't fully understand your recently updated code example, I feel this might be your issue:
while(!Prozess.waitForFinished(2000))
{
std::cerr << "Process running " << std::endl;
}
Wherever you are really calling this in your original code is blocking while waiting for Prozess to finish.
Use a brand new QProcess instance for each one, and connect their finished() signals to a SLOT that will get called when they have finished. Don't manually poll them and block. This will allow you to completely get rid of QThreads altogether.

Qt get a threads ID in the main thread?

I have some issues with this:
First I create my object and move it to a thread:
FileUploader *fileUploader = new FileUploader(fileList_, start, (offset == 0 ? (fileList_.count() - start) : offset));
QThread *fileUploaderThread = new QThread;
fileUploader->moveToThread(fileUploaderThread);
fileUploaderThreads_.append(fileUploaderThread);
fileUploaders_.append(fileUploader); // contains pointers to the objects
connect(fileUploader, SIGNAL(progressChangedAt(int)), model_, SLOT(reportProgressChanged(int)), Qt::QueuedConnection);
connect(fileUploader, SIGNAL(statusChangedAt(int)), model_, SLOT(reportStatusChanged(int)), Qt::QueuedConnection);
connect(fileUploader, SIGNAL(finished()), fileUploaderThread, SLOT(quit()), Qt::QueuedConnection);
connect(fileUploaderThread, SIGNAL(finished()), this, SLOT(checkIfFinished()), Qt::QueuedConnection);
The in the slot checkIfFinished() I wanna go though all the threads and see if they quit.
qDebug() << "one thread done";
foreach(QThread *thread, fileUploaderThreads_) { // or FileUploader* fileuploader, fileUploaders_ ?
if(thread && !thread->isFinished()) {
qDebug() << "not finished " << thread->currentThreadId();
return; // not done
}
}
When this is printed out, I only get the main thread Id, not the threads. I tried to print the threads id's out but with no luck (after they are started ofc).
The reason why I'm doing this I because the person writing "Advanced Qt Programming - Mark S" did a similar thing with QThreads that he placed in a list and checked if they where finished. The only thing thats working now is the connection which kills the thread when the fileUploader is done.
Also, how do I store pointers for the threads? I wounder how I will be able to delete them all if they don't seem to point to the right threads.
Edit:
I tried to store the QObjects in a list instead and do this:
QThread *senderx = qobject_cast<QThread*>(sender());
qDebug() << "one thread done" << senderx;
foreach(FileUploader *fileUploader, fileUploaders_) {
if(fileUploader && !fileUploader->thread()->isFinished()) {
qDebug() << "not finished " << fileUploader->thread();
return; // not done
}
}
//done
qDebug() << "done";
setButtonState(false);
And my outprint on the last call is :
one thread done QThread(0x43ee180)
not finished QThread(0x43ee180)
How is this possible? It is done, but the method says otherwise.
you want QObject::thread(), not QThread::currentThreadId() - the second one returns the thread that the function was called in.
Once you fix that, your pointers will work fine.