基於Qt執行緒另類使用方式。

2022-09-11 17:36:11 字數 3580 閱讀 5196

qt中與執行緒有關的類: qthread、qthreadpool、 qmutex、 qwaitcondition、 qtconcurrent、qfuture、qfuturewacher等等。

例如我在工作中乙個第三方庫不斷持續的**最終呼叫到我類中的乙個方法,我需要傳入乙個,而我需要使用qwidget.renderwidget函式擷取乙個視窗的

並將存為區域性變數,執行緒中再直接給擷取好的,可是因為這樣操作一番,導致效率就降低很多。

1. 因為執行緒不問我要的時候,我的定時器還是在持續的擷取,而且是高頻(30ms擷取一次,因為我並不確定執行緒什麼時候問我要,什麼時候不要,但我

需要給最新的)

2. 即便問我要,我也無法保證是一一對應的,也許執行緒連續兩次問我要的是同一次擷取,也許我擷取了2次,執行緒只問我要了一次,這無疑也是

對cpu無謂的消耗。

於是我就想僅僅因為這一行**,導致我加了很多的邏輯,最終導致**的業務邏輯變得非常複雜,可讀性非常差,可又必須這麼做,有沒有什麼方法

可是將這一行**直接拋給主線程執行呢? 於是我使用lambda運算元進行了封裝:

class invokerhelper : public qobject , public instance;

其中instance實現:

templateclass

instance

};

原始碼如下:

invokerhelper::invokerhelper(qobject *parent) 

: qobject(parent),_bstart(

false

)invokerhelper::~invokerhelper()

void

invokerhelper::start()

void

invokerhelper::quit()

void invokerhelper::execute(const action&action)

void invokerhelper::waitexecute(const action & action, unsigned long

time)

qwaitcondition wait;

execute([&wait, action]()

);qmutex mutex;

mutex.

lock

(); wait.wait(&mutex, time);

mutex.unlock();

}void invokerhelper::slot_executeaction(const action&action)

並且定義這樣兩個巨集:

#define invokemethod invokerhelper::instance().execute

#define invokewait invokerhelper::instance().waitexecute

在實際使用時,在主線程中呼叫:

invokerhelper::instance().start();

invokerhelper::instance().quit();

分別是啟動與退出,看實現其實就是修改乙個變數值,目的是防止主線程退出的時候,

其它執行緒還在往主線程拋東西,這樣會導致崩潰。

如果在main函式的開始或者結束掉用這行**,那麼在程式執行過程,就可以在任何時候將執行緒中

的**拋到主線程並且執行。僅僅只需要對需要拋送的**進行這樣包裝:

invokemethod(() //

這個只是拋送,並不會等待執行完成

);invokewait(()

//這個既拋送到主線程,同時等待執行完成

);

invokerhelper的實現原理就是使用qmetaobject的invokemethod。

qmetaobject::invokemethod(this, "

slot_executeaction

", qt::autoconnection,q_arg(action, action));

//

上面這個類提供了可以在任意其它執行緒(自己執行緒也行,但不需要,除非你自己不確定)將**拋送到主線程的方法。

其實根據上述**的注釋可以知道,拋送到主線程關鍵在於,invokehelper這個單例是在主線程中申明的。

如果我們在乙個有訊息佇列執行緒中宣告乙個invokehelper物件,那麼就可以將任意其它執行緒的**拋送到該執行緒中。於是有下面這樣乙個類:

class kthreadhelper : public qthread, public instance;

.cpp

kthreadhelper::kthreadhelper(qobject*parent)

:qthread(parent),_invokehelper(nullptr)

void kthreadhelper::execute(const action &action)

void kthreadhelper::waitexecute(const action & action, unsigned long

time)

void

kthreadhelper::run()

同樣在主線呼叫:

kthreadhelper::start()

kthreadhelper::quit()

完成這種拋送機制啟動以及關閉,這樣我們可以在任意其它執行緒將指定**拋送執行緒中執行。

例如:對於一些卡介面的行為,就可以直接將其拋送執行緒中執行。

同樣定義了兩個巨集

#define threadcall kthreadhelper::instance().execute

#define threadwait kthreadhelper::instance().waitexecute

值得注意的是,在使用lambda運算元時,由於這是惰性函式,lambda運算元引用的引數一定需要注意其生命週期。

所以專門封裝乙個類用來判斷指標的有效性。

typedef qsetsafepoints;

class thesafepoints : public safepoints, public instance

template

void cut(t*t)

template

bool has(t*t)

qreadwritelock _lock;

};static

qreadwritelock __g_lock;

template

struct

safedelegate

~safedelegate()

};#define safecheck(t) if(!thesafepoints::instance().has(t)) return

當乙個類繼承自safedelegate時,如果該類的物件被析構了,使用safecheck對應的指標可以對該指標進行安全檢查。

QT 執行緒使用總結

解決槽函式響應過程中遇到的阻塞問題 子類化qthread 子類化qobject 1 槽函式相應之前,一定要對操作的物件進行判斷,如果啟動執行緒需要判斷執行緒是否在執行 running 啟動定時器就要判斷定時器是否工作 active 2 兩種方式在開啟執行緒的時候有所不同,第一種由於重寫run函式,因...

遠端爆破,另類結束程序的方式(插入線程式)

老套結束程序方式是openprocess,然後terminateprocess。但是遇到那些hook過terminateprocess的程式,以及核心模式的程式 比如很多防毒軟體 這招就無能為力了。terminateprocess的最終結果是沒有任何變化或者你的程式直接死掉.老早就想過用其他方式來結...

Qt中使用 的方式

先看乙個普通的 類的定義 include using std string class myclass 上述類的定義體現了qt的一些風格 l類名的第乙個字母為大寫,類名包含的單詞使用 駝峰 風格分開,也即每個單詞的第乙個字母為大寫。這是qt類命名的通用方式。l所在方法名的第乙個字母為小寫。單詞之間也...