qt中與執行緒有關的類: qthread、qthreadpool、 qmutex、 qwaitcondition、 qtconcurrent、qfuture、qfuturewacher等等。
例如我在工作中乙個第三方庫不斷持續的**最終呼叫到我類中的乙個方法,我需要傳入乙個,而我需要使用qwidget.renderwidget函式擷取乙個視窗的
並將存為區域性變數,執行緒中再直接給擷取好的,可是因為這樣操作一番,導致效率就降低很多。
1. 因為執行緒不問我要的時候,我的定時器還是在持續的擷取,而且是高頻(30ms擷取一次,因為我並不確定執行緒什麼時候問我要,什麼時候不要,但我
需要給最新的)
2. 即便問我要,我也無法保證是一一對應的,也許執行緒連續兩次問我要的是同一次擷取,也許我擷取了2次,執行緒只問我要了一次,這無疑也是
對cpu無謂的消耗。
於是我就想僅僅因為這一行**,導致我加了很多的邏輯,最終導致**的業務邏輯變得非常複雜,可讀性非常差,可又必須這麼做,有沒有什麼方法
可是將這一行**直接拋給主線程執行呢? 於是我使用lambda運算元進行了封裝:
class invokerhelper : public qobject , public instance;
其中instance實現:
templateclassinstance
};
原始碼如下:
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所在方法名的第乙個字母為小寫。單詞之間也...