Qt信號槽調用方式(emit與QMetaObject::invokeMethod)

最近纔看到在一個線程中接收到數據後需要UI線程刷新時,沒有在子線程中直接刷新,而是用到了QMetaObject::invokeMethod的方法。

QMetaObject::invokeMethod(this, "changeState", Q_ARG(int, 0), Q_ARG(int, m_nSingleState), Q_ARG(int, 0));
void myClass::OutputState(int nType, int nParam1, int nParam2)
{
	switch (nType)
	{
	case 0:
	{

	}
	break;
	case 1:
	{
		int nCaptureLength = nParam1;
		........
	}
	break;
	case 2:
	{
		int nTime = nParam1;
		........
	}
	default:
		break;
	}
}
connect(this, &myClass::changeState, this, &myClass::OutputState);

1. 爲什麼需要用invokeMethod而不是emit呢?

一般來說,我們使用invokeMethod是在子線程需要調度UI操作的時候。主要有一下原因:

  a. 使用 QMetaObject :: invokeMethod 的原因是收件人對象可能在另一個線程中,如果試圖直接在另一個線程中的對象上調用一個槽訪問或修改非線程安全數據,則會導致損壞或更糟。

b. 我們可以自己定義連接方式。但是需要注意具體問題具體分析。

 

 

2. 簡單介紹一下invokeMethod

bool QMetaObject::invokeMethod(QObject *obj, 
             const char *member, 
             Qt::ConnectionType type, 
             QGenericReturnArgument ret, 
             QGenericArgument val0 = QGenericArgument( Q_NULLPTR ), 
             QGenericArgument val1 = QGenericArgument(), 
             QGenericArgument val2 = QGenericArgument(), 
             QGenericArgument val3 = QGenericArgument(), 
             QGenericArgument val4 = QGenericArgument(), 
             QGenericArgument val5 = QGenericArgument(), 
             QGenericArgument val6 = QGenericArgument(), 
             QGenericArgument val7 = QGenericArgument(), 
             QGenericArgument val8 = QGenericArgument(), 
             QGenericArgument val9 = QGenericArgument())
             
觸發obj對象裏面的memeber,member是一個信號/槽的名字。如果正確被觸發返回true.
調用可以是同步的,也可以是異步的,具體取決於類型:
如果類型爲qt::directconnection,則將立即調用該成員。
如果類型爲qt::queuedconnection,則在應用程序進入主事件循環後,將發送qEvent並調用成員。
如果類型爲qt::blockingqueuedconnection,則將以與qt::queuedconnection相同的方式調用該方法,但當前線程將阻塞,直到傳遞事件爲止。使用此連接類型在同一線程中的對象之間進行通信將導致死鎖。
如果類型爲qt::autoconnection,則如果obj與調用方位於同一線程中,則會同步調用該成員;否則,它將異步調用該成員。
成員函數調用的返回值放在ret中。如果調用是異步的,則無法計算返回值。最多可以向成員函數傳遞十個參數(val0、val1、val2、val3、val4、val5、val6、val7、val8和val9)。

QGenericArgument and QGenericReturnArgument are internal helper classes. Because signals and slots can be dynamically invoked, you must enclose the arguments using the Q_ARG() and Q_RETURN_ARG() macros. Q_ARG() takes a type name and a const reference of that type; Q_RETURN_ARG() takes a type name and a non-const reference.
QGenericArgument和QGenericReturnArgument是內部幫助程序類。由於可以動態調用信號和插槽,因此必須使用q_arg()和q_return_arg()宏將參數括起來。q_arg()接受類型名和該類型的常量引用;q_return_arg()接受類型名和非常量引用。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章