簡體   English   中英

添加用於偵聽網絡的新線程時,應用程序凍結

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

我通過Start_zeroMQResponderThread函數Start_zeroMQResponderThread使用Qt開發的應用程序添加了新線程:

// 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();
}

我在MainWindow的構造函數中調用了此函數,以確保在應用程序的開頭創建線程:

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();
}

最后,這是函數Run_zeroMQResponderThread() :它在單獨的線程中運行。 它啟動一個無限循環,以使用ZeroMQ檢測發送的消息,並使用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);


}

在添加此功能之前,該應用程序運行良好。 但是添加后,它凍結在應用程序的開頭,甚至沒有顯示應用程序的主界面。

可能是什么問題呢?

QWidget移動到除主線程或null線程之外的任何線程上並不是要工作的。 期間

無論如何,您應該從UI中考慮代碼的控制器方面。 控制器將駐留在一個或多個QObject 您所要做的就是將它們移到工作線程中,然后就可以設置好了。

提供的代碼並未指示您使用哪種方法來實現線程功能。

  1. 我假設你的zeroMQResponderthread是一個QThread對象
  2. 該QThread的,對象本身不應通過moveToThread移動到自身。 QThread是一個對象,應該在創建QObject的上下文中保留(在本例中為您的MainWindow)。

為了解決您的問題,請創建一個從QObject派生的新類(包括聲明中的Q_OBJECT標志),提供一個插槽,該插槽可以完成Run_zeroMQResponderThread()中當前完成的工作,並將該插槽連接到QThread-Object的started( )信號。

它看起來應該像這樣:

// 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();

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM