Qt线程(1)

来源:互联网 发布:dxv解码器 for mac 编辑:程序博客网 时间:2024/06/04 19:53

在PictureBook Connector里初始使用的线程结构为

// SocketThread.hSocketThread : QThread{protected:    virtual run();};// SocketThread.cppvoid SocketThread :: run(){    QTcpSocket tcpSocket;    if(!tcpSocket.setSocketDescriptor(socketDescriptor)) {        emit error(tcpSocket.error());        return;    }    // can't connect slot    // connect(&tcpSocket, SIGNAL(disconnected()), this, SLOT(quit()), Qt::QueuedConnection);    tcpSocket.moveToThread(this);    while( !m_quit && tcpSocket.state() == QAbstractSocket::ConnectedState ) {        // ...    }}

因为需求的原因,需要将代码中的connect注释掉的代码打开,以使得在socket断掉的时候可以将thread退出。
但是却发现不能触发信号与槽,在一位同行的介绍下,在QtHelp里看了Multithreading Technologies in Qt。

Lifetime of thread Operation Solution One call Run a new linear function within another thread, optionally with progress updates during the run. Qt provides different solutions: 1- Place the function in a reimplementation of QThread::run() and start the QThread. Emit signals to update progress. OR 2- Place the function in a reimplementation of QRunnable::run() and add the QRunnable to a QThreadPool. Write to a thread-safe variable to update progress. OR 3- Run the function using QtConcurrent::run(). Write to a thread-safe variable to update progress. One call Run an existing function within another thread and get its return value. Run the function using QtConcurrent::run(). Have a QFutureWatcher emit the finished() signal when the function has returned, and call QFutureWatcher::result() to get the function’s return value. One call Perform an operation on all items of a container, using all available cores. For example, producing thumbnails from a list of images. Use Qt Concurrent’s filter() function to select container elements, and the map() function to apply an operation to each element. To fold the output into a single result, use filteredReduced() and mappedReduced() instead. One call/Permanent Perfrom a long computation in a pure QML application, and update the GUI when the results are ready. Place the computation code in a .js script and attach it to a WorkerScript instance. Call sendMessage() to start the computation in a new thread. Let the script call WorkerScript::sendMessage() too, to pass the result back to the GUI thread. Handle the result in onMessage and update the GUI there. Permanent Have an object living in another thread that can perform different tasks upon request and/or can receive new data to work with. Subclass a QObject to create a worker. Instantiate this worker object and a QThread. Move the worker to the new thread. Send commands or data to the worker object over queued signal-slot connections. Permanent Repeatedly perform an expensive operation in another thread, where the thread does not need to receive any signals or events. Write the infinite loop directly within a reimplementation of QThread::run(). Start the thread without an event loop. Let the thread emit signals to send data back to the GUI thread.

我们可以看到在Permanent(无尽的)相关的介绍

  • 最下面一行是C的写法,即在run函数里写while(true){…},里面明确写了不要在while里使用connect连接
  • 在倒数第二行里,其写的用worker.moveToThread(thread);的写法,其可以将worker进行信号与槽的连接
  • 倒数第三行这种用法还没有适应,暂时不考虑

so…我现在将我的socketThread里run函数里的code给封装成一个SocketWorker类。


  1. connect(pThread, SIGNAL(finished()), pThread, SLOT(deleteLater())); 1
  2. 然后在Socket断掉的时候,调用pThread.terminate()函数。

其现象非常有意思,感觉像是主线程被terminate掉的,但是UI没有断掉,只不过所有事件全部丢失。

把1中的connect代码去掉,则正常。


在进行Worker类进行设计时有两种思路:

  • SocketWorker : QObject { QTcpSocket * m_pSocket; }
  • SocketWorker: QTcpSocket

第一种在使用的时候,编译器报Warning,大体意思就是本地的Socket不能新建在与父线程不同的线程里,然后列出QTcpSocket 与SocketWorker的各自的ThreadId。

其结果是Socket第一次可以正常读写,第二次客户端发来的data就不能触发QTcpSocket::readyread信号。

根据我的分析应该是这样的情况:
SocketWorker->moveToThread(pThread);时QTcpSocket不是线程安全,而导致SocketWorker切换线程时,不能在其他线程触发事件。

第二种没有任何问题。

0 0