简体   繁体   中英

Application freezes when adding a new thread for listening to the network

I added a new thread to my application developed using Qt through the function Start_zeroMQResponderThread :

// this function adds the new thread
void MainWindow::Start_zeroMQResponderThread()
{

    moveToThread(&zeroMQResponderthread);
    QObject::connect(&zeroMQResponderthread, SIGNAL(started()), this, SLOT(Run_zeroMQResponderThread())); //cant have parameter sorry, when using connect
    zeroMQResponderthread.start();
}

I called this function in the constructor of MainWindow to be sure that the thread is created in the start of the application:

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
....

    // This is the sender which do not need to be run in a separate thread
    context = zmq_ctx_new();
    requester = zmq_socket(context, ZMQ_PAIR);
    rc = zmq_connect(requester, "tcp://10.131.7.97:5555"); 
...
    //  This is the starting of the thread that will listens to the network to 
    //  capture received messages using ZeroMQ
    Start_zeroMQResponderThread();
}

And Finally, this is the function Run_zeroMQResponderThread() : It runs in the separate thread. It launches an infinite loop to detect sent messages using ZeroMQ and transforms them to vocal messages using Windows Text To Speech API (SAPI):

void MainWindow::Run_zeroMQResponderThread() {

    ISpVoice * pVoice = NULL;
    if (!FAILED(::CoInitialize(NULL)))
    {
        HRESULT hr = CoCreateInstance(CLSID_SpVoice, NULL, CLSCTX_ALL, IID_ISpVoice, (void **)&pVoice);
    }


    void *context = zmq_ctx_new();
    void *responder = zmq_socket(context, ZMQ_PAIR);
    int rc = zmq_bind(responder, "tcp://*:5555");


    printf("Receiver: Started\n");

    char buffer[128];
    wchar_t wtext[128];
    while (true)
    {
        int num = zmq_recv(responder, buffer, 128, 0);

        if (num > 0)
        {
            buffer[num] = '\0';
            printf("Receiver: Received (%s)\n", buffer);



            mbstowcs(wtext, buffer, strlen(buffer) + 1);//Plus null
            LPWSTR ptr = wtext;
            HRESULT hr;
            if (pVoice)
                hr = pVoice->Speak(ptr, SPF_DEFAULT, NULL);

            if (!SUCCEEDED(hr))
                std::cout << "speak error" << hr << std::endl;
        }
    }

    pVoice->Release();
    pVoice = NULL;
    ::CoUninitialize();

    zmq_close(responder);
    zmq_ctx_destroy(context);


}

Before adding this function, the application runs well. But after adding it freezes at the beginning of the application without even showing the main UI of the application.

What could be the problem?

Moving a QWidget to any thread other than the main thread or null thread was not ever meant to work. Period .

You should factor out the controller aspect of your code from the UI anyway. The controller will reside in one or more QObject s. All you have to do is move those to a worker thread, and you're set.

The code provided does not indicate which method you are using to achieve threaded functionality.

  1. I assume your zeroMQResponderthread is a QThread Object
  2. The QThread-Object itself should NOT be moved to itself via moveToThread. The QThread is an Object that should remain in the context of it's creating QObject (your MainWindow in this case).

To solve your problem, create a new class which derives from QObject (including the Q_OBJECT flag in the declaration), give a slot which does the work which is currently done in your Run_zeroMQResponderThread() and connect this slot to your QThread-Object's started() signal.

It should look like this:

// parent of the QObject superclass should be 0 upon creation
WorkObject *wobject = new WorkObject(); 
// using 'this' so the workerthread gets deleted when the mainwindow is deleted
QThread *worker = new QThread(this); 
// move workobject to worker
wobject->moveToThread(worker);
// do work as soon as worker starts
QObject::connect(worker, SIGNAL(started()), wobject, SLOT(doWork()));
// delete workobject when worker finishes
QObject::connect(worker, SIGNAL(finished()), wobject, SLOT(deleteLater()));
// start worker
worker->start();

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM