Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

CreateWindow() for QEventDispatcherWin32 internal window failed



  • Hello All,

    I'm working multithreading application and I'm not that expert in using multithreading applications.
    Find my implementation below and help me with these errors as mentioned in the title.

    //Worker Class
    class LogWorker: public QObject
    {
        Q_OBJECT
    
    public:
        explicit LogWorker(QObject *parent = nullptr)
        {
            qRegisterMetaType<HashType>("HashType");
        }
    
        QString m_file;
        QHash<QString, QList<QPair<QString, QString>>> m_settings;
    
    public slots:
        void updateData()
        {
            JsonParser *parser = new JsonParser;
            parser->setJson(m_file);
            HashType gDATA;
            QHashIterator<QString, QList<QPair<QString, QString>>> i(m_settings);
            while (i.hasNext())
            {
                QList<s_DATA> pairData;
                auto list = i.next();
                foreach (auto pair, list.value())
                {
                    s_DATA sdta;
                    int count = parser->dataCount(pair.second, NULL, false);
                    sdta._d = pair.first;
                    sdta._q = pair.second;
                    sdta._c = count;
                    pairData.append(sdta);
                    QCoreApplication::processEvents();
                };
    
                gDATA.insert(i.key(), pairData);
            }
                QCoreApplication::processEvents();
    
            delete parser;
            emit update(m_file, gDATA);
        }
    
    signals:
        void update(QString file, HashType gdata);
    };
    
    //Service Class 
    class LogService : public QObject
    {
        Q_OBJECT
    
    public:
        explicit LogService(QHash<QString, QList<QPair<QString, QString>>> settings, QObject *parent = nullptr)
            :m_settings(settings)
        {
            qRegisterMetaType<HashType>("HashType");
        }
        ~LogService()
        {
        }
    
        void updateFile(QString file)
        {
            QThread *thread = new QThread(this);
            worker = new LogWorker;
            worker->m_file = file;
            worker->m_settings = m_settings;
    
    
            worker->moveToThread(thread);
    
            connect(thread, &QThread::started, worker, &LogWorker::updateData);
            connect(worker, &LogWorker::update, this, [this, thread](QString file, HashType gdata){
                insertData(file, gdata);
                thread->quit();
                thread->wait();
            });
            connect(thread, &QThread::finished, worker, &QObject::deleteLater);
    
            thread->start();
        }
    
        void insertData(QString key, HashType value)
        {
            QMutex mutex;
            QMutexLocker locker(&mutex);
            hashData.insert(key, value);
        }
    
    private:
        QThread *thread;
        LogWorker *worker;
        QHash<QString, QList<QPair<QString, QString>>> m_settings;
        QHash<QString, HashType> hashData;
    
    };
    

    I'm calling LogService from the main code

    LogService *controller = new LogService(allSettings);
    
            foreach (QString file, filepaths)
            {
                controller->updateFile(file);
            }
    

    Note:

    • Threads are not depend on each other
    • In insertData(QString key, HashType value), I have added mutex because I want every thread should update the variable properly, and not create deadlock condition.

    The filepaths are nearly 30 to 40 thousands file in the above code. I didn't get any error on compiling or running lesser number fo files. But when I pass files with 30 thousand then it's giving me the error shown below.

    unknown(0)[33888]: CreateWindow() for QEventDispatcherWin32 internal window failed (The current process has used all of its system allowance of handles for Window Manager objects.)
    unknown(0)[30740]: CreateWindow() for QEventDispatcherWin32 internal window failed (The current process has used all of its system allowance of handles for Window Manager objects.)
    unknown(0)[30740]: Qt: INTERNAL ERROR: failed to install GetMessage hook: 1158, The current process has used all of its system allowance of handles for Window Manager objects.
    

    Can someone help me where I have mistaken?


  • Lifetime Qt Champion

    @npatil15 Why do you create a thread for each file?!
    It does not make any sense to create more threads than logical cores in your CPU, even less so 30.000-40.000!



  • @jsulm , I'll explain what I understood while implemeting this.
    Here I'm creating threads normally 30k, but I'm considering QThreads managing to running only 8(based QThread::idealThreadCount()) threads at once parallelly and in this way, it will manage all 30k threads to run in pips of 8.

    Now I create a thread per file because here I'm loading JSON file and I have created a script that extracts data from that JSON file and adds extracted data to hashData. So I was thinking if it runs in a pipe of 8 then I can reduce processing time with 8 times.

    Also for solution I have found QThreadPool, but in this, I don't understand how I can update hashData or update any global variable because it doesn't use the signal/slot mechanism.


  • Lifetime Qt Champion

    @npatil15 said in CreateWindow() for QEventDispatcherWin32 internal window failed:

    Now I create a thread per file

    You should not do that! You're wasting resources.

    Create QThread::idealThreadCount() threads and pass work packages to them (files in your case). If a thread signals that it finished its work package give it next file.



  • @jsulm This thing I'm not getting how to implement it.

    I can run QThread::idealThreadCount() threads, but I don't understand how to manage this?



  • @npatil15

    1. Count as you create each thread.
    2. Stop creating new threads when you reach the "ideal thread count".
    3. At that point, only create the next thread when you receive signal stating that one of the previously-created threads has terminated, so that another thread is available to create.
    4. Keep doing that until you have processed all your file paths or whatever.


  • I have created counting QSemaphore idealthread{QThread::idealThreadCount()} as a private member of LogService Class
    So I acquire() in void updateFile(QString file)
    and release() in void insertData(QString key, HashType value).

    I think with this approach I can allow running only QThread::idealThreadCount() threads at once and as soon as any semaphore release, it again runs the loop and add one more thread and again stops. It looks workable but facing some issue, explain below.

    So when I updateFile(), it creates a thread, acquires the semaphore, and starts the processing and then after the finish, emits the signal update() and is connected to insertData() where it releases the semaphore.
    I can see it create 8 threads and then just stopped creating a new thread, obvious because it's not releasing the semaphore, and it's only because it's not emitting the signal, where it suppose to release it as explained above.

    But there are strange things that it doesn't emit update(m_file, gDATA) signal.

    I have added debug, and it's reaching there but not emitted the signal where if I remove semaphore it works fine.

    What is wrong with this?



  • By forcing Direct connection works well now,
    connect(worker, &LogWorker::update, this, &LogService::insertData, Qt::DirectConnection);

    But now I'm again facing the same error as mentioned in the first time,

    unknown(0)[34908]: CreateWindow() for QEventDispatcherWin32 internal window failed (The current process has used all of its system allowance of handles for Window Manager objects.)
    unknown(0)[34908]: Qt: INTERNAL ERROR: failed to install GetMessage hook: 1158, The current process has used all of its system allowance of handles for Window Manager objects.
    unknown(0)[1040]: CreateWindow() for QEventDispatcherWin32 internal window failed (The current process has used all of its system allowance of handles for Window Manager objects.)
    unknown(0)[1040]: Qt: INTERNAL ERROR: failed to install GetMessage hook: 1158, The current process has used all of its system allowance of handles for Window Manager objects.
    

    I have read about it and it's saying you are not making objects null or releasing it properly somewhere because normally window adds limits on creating objects.


  • Lifetime Qt Champion

    Hi,

    There are several problems in your code. For example your mutex declared in a function is useless because it's recreated each time that function is called so there's no protection done.

    Second is if you need to start fiddling with the connection type to makes things working, you are doing something wrong.

    In any case, to avoid starving your machine like you are doing I would recommend going one level higher. Either use QThreadPool or QtConcurrent. These are higher level classes to ease the use of threading. You will have cleaner and simpler code with less to worry about thread management.

    Concentrate on your file handling and let the framework handle the threads.


Log in to reply