1. 能否跨執行緒呼叫tcp套接字?
對於tcp通訊,乙個常見的操作就是讀寫分開,即讀寫分別在不同執行緒中執行,這樣實現實時全雙工通訊,那麼在qt中能否實現讀寫執行緒分開呢?理論上將是不可以的,但是實際操作發現能實現(會有錯誤警告)。
這涉及到訊號和槽的連線方式。通常qt的訊號和槽有三種常用的連線方式:
(1) qt::autoconnection:qt預設連線方式。當訊號接收方與訊號傳送方在同一執行緒時,等價於qt::directconnection;否則等價於qt::queuedconnection。
(2) qt::directconnection: 當訊號被傳送後,槽函式立即執行。這對於實時通訊意義重大,如ui介面傳送tcp訊息之後,需要實時等待tcp響應以進行不同的操作,這種連線方式就能保證tcp能立即傳送訊息。
2 紅色部分是修改部分,即採用了qt::directconnection。由於訊號傳送方在ui執行緒,接收方在tcp子執行緒,所以此時呼叫的槽函式不會在子執行緒中執行,而是直接在ui執行緒執行,這樣收發在不同執行緒,都能實時響應。這種做法雖然沒有影響收發效果,但是每次會提示socket notifiers cannot be enabled or disabled from another thread,從提示結果就能看出這是跨執行緒呼叫tcp造成的。這種提示的後果未知(因為程式仍能正常執行)。
2. 如何優化設計
雖然1所介紹的方案能實現功能,但是畢竟出現錯誤提示,不知道會造成何種後果。所以最好還是不採用以上方式。那麼對於tcp的收發,如何做到實時響應呢?
造成1中的程式原因是在tcp子執行緒一直迴圈接收tcp資料,這種操作是非常不明智的。為了讓tcp子執行緒空閒,只在收發資料時執行,可以將tcp接收也改為訊號和槽的形式。tcp收到訊息時,會傳送訊號qtcpsocket::readyread,通過該訊號與tcp接收繫結,就不用在子執行緒中迴圈呼叫tcp接收函式了。改造後的tcpmodel如下:
1主要改動都用紅色標出了,特別注意:2 3 #ifndef tcpmodel_h
4 #define tcpmodel_h
5 #include 6 #include 7 #include 8
9 class tcpmodel:public qobject
10 ;
31 32 //將tcpmodel在qml初始化時移入到子執行緒
33 class tcpmovetothread: public qobject
34 ;
55 56 #endif // tcpmodel_h
57 58
59 60 #include "tcpmodel.h"
61 #include 62
63 tcpmodel::tcpmodel(qobject* parent)
64 66
67 void tcpmodel::tcpwork()
68 73
74 void tcpmodel::tcpclose()
75 79
80 void tcpmodel::tcpsendmsgslot(qstring msg)
81 85
86 void tcpmodel::tcprecvslot()
87 94 }
95 96
97 98 tcpmovetothread::tcpmovetothread(qobject* parent)
99 111
112 tcpmovetothread::~tcpmovetothread()
113
117
118 void tcpmovetothread::datachangedslot(qstring msg)
119
第83行:qt的tcp通訊預設都是非同步的,所以即時呼叫了write和read函式,也可能不會立即進行讀寫,表現在程式中就是能立即執行槽函式,但tcp收發有明顯延遲(可以將83注釋掉,再看現象)。所以為了將非同步改為同步,qt的tcp規定了以下函式:
waitforconnected() 等待鏈結的建立
waitforreadyread() 等待新資料的到來
waitforbyteswritten() 等待資料寫入socket
waitfordisconnected() 等待鏈結斷開
QT下多執行緒呼叫TCP的問題及可能的解決方案
1.能否跨執行緒呼叫tcp套接字?對於tcp通訊,乙個常見的操作就是讀寫分開,即讀寫分別在不同執行緒中執行,這樣實現實時全雙工通訊,那麼在qt中能否實現讀寫執行緒分開呢?理論上將是不可以的,但是實際操作發現能實現 會有錯誤警告 這涉及到訊號和槽的連線方式。通常qt的訊號和槽有三種常用的連線方式 1 ...
QT下的多執行緒
一.多執行緒的使用 繼承qthread類,重寫protected void run 函式,則此run函式即為多執行緒將執行的函式,ui類組合此類,呼叫start 函式即開啟此執行緒,並執行run函式 h class test1 public qthread cpp void test1 run vo...
Qt多執行緒中呼叫QTimer
ifndef mythread h define mythread h include class qtimer class mythread public qthread endif mythread h 原始檔如下 include mythread.h include include mythr...