簡體   English   中英

QThread 來回傳遞數據

[英]QThread passing data to and from

我將嘗試解釋我的程序曾經做什么以及我想改變什么:

我有一個從類 MainWindow 的主線程單擊按鈕時運行的函數:public QMainWindow:

該函數如下所示,並在另一個文件中指定:

void MakeMeshStructure(MeshStructureLayers layers,
                      Handle_AIS_InteractiveContext theContext,
                      Handle_TDocStd_Document aDoc,
                      MyMesh &mesh,
                      int detail_vertex,
                      double insulation_thickness,
                      OpenMesh::VPropHandleT<MyMesh::Scalar> _max_beam_offset);
}

它的作用是:它在網格上工作並為網格的每個頂點、面和邊創建幾何體。 該幾何與上下文一起顯示。 此過程需要很長時間(30 分鍾)並阻止圖形用戶界面。

我想做的是擁有與 QThread::idealThreadCount() 一樣多的線程,並在計算時釋放 gui 並使其更快。 (這是正確的想法嗎?)

我想將我的網格分成相等的部分,並將這一范圍的頂點傳遞給我的函數(上圖),以便僅使用一個頂點范圍來處理單獨的胎面。

我有一個問題要弄清楚如何傳遞這些數據並使其線程安全。 我知道它的很多代碼,但這是我嘗試解決它的嘗試:

http://pastebin.com/u/mzagar

問題是以正確的方式獲取所有數據並讓線程工作。 我必須在哪里使用互斥鎖。 在主線程線程工作時可以寫入的每個數據上? 很困惑。

編輯:

我編輯了我的代碼: http ://pastebin.com/u/mzagar 我做了一個 struct cadData 來傳遞數據。 這就是我啟動線程的方式:

connect(this, SIGNAL(startMake1(cadData)), cThreads.at(0), SLOT(MakeMesh(cadData)));
//...
cThreads.at(0)->moveToThread(threads.at(0));
//...
threads.at(0)->start();
 //...
emit startMake1(aCadDatas.at(0));
 //...

問題是線程似乎不能同時工作,而且 gui 會凍結。 過程是這樣的:

  • GUI 凍結
  • 線程 1 中的事情完成
  • 線程 1 中的事情再次完成
  • 線程 2 中的事情完成了
  • 線程 2 中的事情再次完成
  • ...
  • GUI 解凍

任何想法為什么?

編輯2:

我通過將其移至類構造函數來刪除同一線程的多次運行:

connect(this, SIGNAL(startMake1(cadData)), cThreads.at(0), SLOT(MakeMesh(cadData)));
//...
cThreads.at(0)->moveToThread(threads.at(0));
//...
threads.at(0)->start();

由於您使用的是 QThread,因此您可以通過使用 Qt 的線程安全槽和信號機制來為您完成工作,從而避免顯式使用互斥鎖等。 您基本上會將需要發送到線程的數據打包到一個對象中,然后發出一個將該對象作為參數的信號。 該線程將在插槽(您之前已連接到信號)中接收該對象的副本,然后開始使用數據。 要將數據從工作線程返回到主線程,您需要以相反的方式再次執行相同的操作。 是一篇帶有一些示例代碼的文章。

添加到 Jeremy 的回答:您可以通過在 QObjects 之間發送事件而不是使用信號槽機制來做同樣的事情。 使用對您來說最方便的那個。

關鍵是利用 Qt 的內置事件循環互斥體。 當您向與發送者不同的線程中的對象發送信號時,該信號將轉換為 QMetaCallEvent 並發布到接收 QObject 的事件隊列中。 當然,這是以線程安全的方式完成的,你所要做的就是利用它。 發送顯式事件的方式相同。 在接收者所在的線程中旋轉的事件循環簡單地獲取 QMetaCallEvents 並相應地執行槽調用,或者將您的事件分派給您的customEvent()方法的實現。

當您啟動原始QThread時, run()方法的默認實現會啟動一個事件循環。 您會注意到這樣的線程實際上是空閑的並且不消耗任何 CPU 資源:事件隊列是空的,事件循環被阻塞,等待有人將事件發布到它的隊列中。 一旦你將一些 QObjects 移動到這樣的線程,排隊的信號槽傳遞將通過該線程的事件循環完成。 無論是 GUI 線程還是任何其他線程,它的工作原理都是一樣的。 GUI 線程在接收事件或排隊信號方面沒有任何特殊之處。

暫無
暫無

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

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