QThread correct usage
Unsolved
General and Desktop
-
Hi everyone!
I have a images gallery application. All images I'm loading in QThread. In QtCreator all works fine (Release and Debug mode). But if I try to load my app just click on MyApplication.app I can't get images list only at first time. When I try to refresh the list I'm receiving error:
2018-07-20 12:48:36.834 ShavSample[15543:506104] Persistent UI failed to open file file:///Users/andrewsh/Library/Saved%20Application%20State/com.consultica.ShavSample.savedState/window_1.data: Too many open files (24) QThreadPipe: Unable to create pipe: Too many open files QEventDispatcherUNIXPrivate(): Can not continue without a thread pipe Abort trap: 6
I'm using Qt 5.11 on macOS 10.13.6.
Create a worker:ShavGetImagesInfoWorker* worker = new ShavGetImagesInfoWorker(urls, callback); if(!ShavTaskManager::isObjectCreated()) { ShavTaskManager::initManager(); } ShavTaskManager::shared()->startWork(worker);
Start thread:
if(worker) { m_tasks.append(worker); QThread* newThread = new QThread(); connect(newThread, &QThread::started, worker, &ShavThreadWorker::run); connect(worker, &ShavThreadWorker::finished, this, &ShavTaskManager::onFinished); connect(worker, &ShavThreadWorker::finished, newThread, &QThread::quit); connect(newThread, &QThread::finished, newThread, &QObject::deleteLater); worker->moveToThread(newThread); newThread->start(static_cast<QThread::Priority>(priority)); }
All worker is a subclass from class:
class ShavThreadWorker : public QObject { Q_OBJECT private: ShavTaskResult* m_result; ShavTaskResult* m_progress; QMutex m_mutex; protected: virtual QObject* doTaskAction(); void updateProgress(QVariant value, QVariant total, QVariant userData = QVariant()); public: explicit ShavThreadWorker(QJSValue callback, QObject *parent = nullptr); explicit ShavThreadWorker(QJSValue callback, QJSValue progress, QObject *parent = nullptr); ~ShavThreadWorker(); signals: void finished(); private slots: inline void onFinishedResult() { emit finished(); } public slots: void run(); inline void stop() { this->thread()->requestInterruption(); } };
and implementation of calls:
QObject *ShavThreadWorker::doTaskAction() { return nullptr; } void ShavThreadWorker::updateProgress(QVariant value, QVariant total, QVariant userData) { if(userData.isNull()) { QMetaObject::invokeMethod(m_progress, "updateProgress", Qt::QueuedConnection, Q_ARG(QVariant, value), Q_ARG(QVariant, total)); //Main thread } else { QMetaObject::invokeMethod(m_progress, "updateProgress", Qt::QueuedConnection, Q_ARG(QVariant, value), Q_ARG(QVariant, total), Q_ARG(QVariant, userData)); //Main thread } } ShavThreadWorker::ShavThreadWorker(QJSValue callback, QObject *parent) : QObject(parent) { static int index = 0; setObjectName(QString("%1_%2").arg(metaObject()->className()).arg(index)); index += 1; m_result = new ShavTaskResult(callback); connect(m_result, SIGNAL(finished()), SLOT(onFinishedResult())); m_progress = nullptr; } ShavThreadWorker::ShavThreadWorker(QJSValue callback, QJSValue progress, QObject *parent) : QObject(parent) { static int index = 0; setObjectName(QString("%1_%2").arg(metaObject()->className()).arg(index)); index += 1; m_result = new ShavTaskResult(callback); connect(m_result, SIGNAL(finished()), SLOT(onFinishedResult())); m_progress = new ShavTaskResult(progress); } ShavThreadWorker::~ShavThreadWorker() { #ifdef QT_DEBUG qDebug()<<metaObject()->className()<<"was released!"; #endif } void ShavThreadWorker::run() { m_mutex.lock(); QObject* res = doTaskAction(); if(m_result != nullptr) { res->moveToThread(qApp->thread()); QMetaObject::invokeMethod(m_result, "sendResult", Qt::QueuedConnection, Q_ARG(QObject*, res)); //Main thread } else { onFinishedResult(); } m_mutex.unlock(); }
-
The closest i have to an example is https://github.com/VSRonin/ChatExample/blob/master/QtSimpleChatServerThreaded/chatserver.cpp