最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

C++判斷QMetaObject::invokeMethod()里的函數(shù)是否調(diào)用成功

 更新時(shí)間:2025年07月16日 08:49:36   作者:sanqima  
本文詳細(xì)介紹里的invokeMethod()函數(shù)的2種調(diào)用方式,包括同步調(diào)用、異步調(diào)用,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

今天,在Qt編程,碰到一個(gè)需要使用invokeMethod方式來獲取函數(shù)是否執(zhí)行成功的情況。

invokeMethod()即可以同步調(diào)用,也可以異步調(diào)用。若調(diào)用者、被調(diào)用者,都在同一個(gè)線程,則是同步調(diào)用;若調(diào)用者、被調(diào)用者,在不同線程,則是異步調(diào)用。

注意:只有同步調(diào)用,才能通過invokeMethod()的返回值,來判斷函數(shù)是否執(zhí)行成功。

比如,有如下精簡代碼:

//1)業(yè)務(wù)代碼
class ComWork : public QObject {
 Q_OBJECT
public:
	ComWork();
	
signals:
   void sigSendResult(bool bOK);

public slots:
    void SendCommand(QByteArray by) {
    	qint64 nRet = m_pSerial->write(by);
    	bool bOK = (nRet != -1);
    	if(bOK)
    	   m_pSerial->flush();
    	emit sigSendResult(bOK);
    } 

private:
   QSerialPort* m_pSerial;
};

//2) 界面邏輯代碼
class ZoomWidget : public QWidget {
public:
	ZoomWidget (QWidget *parent= NULL);

protected slots:
    void OnRecvCmdResult(bool bOK);

private:
    QThread* m_pThread; //子線程
    ComWork* m_pWork;
    bool     m_bResult;
};


ZoomWidget ::ZoomWidget (QWidget *parent)
    : QWidget(parent)
{
    ui.setupUi(this);

    m_pThread = new QThread(this);
    m_pWork   = new ComWork();
    m_pWork->moveToThread(m_pThread); //m_pWork移動到子線程里,語句(a)

    //連接信號,語句(b)
    connect(m_pWork,&m_pWork::sigSendResult,this,ZoomWidget::OnRecvCmdResult);
}

ZoomWidget::OnRecvCmdResult(bool bOK)
{
	m_bResult = bOK; //語句(c)
	qDebug()<<"recv status:"<<bOK;
}

// 3)核心調(diào)用
ZoomWidget::DoSend()
{
    //進(jìn)行調(diào)用,語句(d)
	QMetaObject::invokeMethod(m_pWork, "SendCommand", Qt::QueuedConnection, Q_ARG(QByteArray, sendData));
}

在Qt中,UI對象必須在主線程。而ZoomWidget是一個(gè)QWidtget,屬于UI對象,即ZoomWidget在主線程。

由語句(a)可知,m_pWork移動到了子線程里,即ZoomWidget與m_pWork不在同一個(gè)線程,
則在調(diào)用DoSend()函數(shù)時(shí),QMetaObject::invokeMethod(m_pWork,…)其實(shí)是跨線程調(diào)用,也就是異步調(diào)用。而異步調(diào)用,由于"它不會等待函數(shù)是否執(zhí)行,就直接返回了",即invokeMethod(,…Qt::QueuedConnection ,)函數(shù),不會等待m_pWork的SendCommand()是否執(zhí)行,就直接返回,并給出一個(gè)返回值,該返回值是無效的。

如果強(qiáng)制返回,Qt編譯也會報(bào)"QMetaMethod::invoke: Unable to invoke methods with return values in queued connections"錯(cuò)誤。

但可以通過信號槽的方式,把異步調(diào)用的結(jié)果(比如語句(b)、語句©),返回給調(diào)用者(比如本例的ZoomWidget)。

這個(gè) "Unable to invoke methods"的Qt 編譯報(bào)錯(cuò):

QMetaMethod::invoke: Unable to invoke methods with return values in queued connections

是一個(gè)非常常見的運(yùn)行時(shí)錯(cuò)誤,它的含義是:

你試圖使用 Qt::QueuedConnection(即異步方式)調(diào)用一個(gè)帶有返回值的方法,而這是 Qt 不支持的。

錯(cuò)誤原因詳解

什么是Qt::QueuedConnection?

  • 它表示方法調(diào)用會在目標(biāo)對象所在的線程中排隊(duì)執(zhí)行(異步調(diào)用),而不是立即執(zhí)行。
  • 常用于跨線程通信,比如從子線程調(diào)用主線程的 UI 方法。

為什么不能在Qt::QueuedConnection中使用帶返回值的函數(shù)?

  • 因?yàn)樗?strong>異步調(diào)用,調(diào)用者不會等待函數(shù)執(zhí)行完成。
  • 所以無法通過 Q_RETURN_ARG(...) 拿到函數(shù)的返回值。
  • Qt 在底層會檢測這一點(diǎn),并拋出警告或?qū)е路祷刂禑o效。

示例代碼:錯(cuò)誤寫法

int result = 0;
bool success = QMetaObject::invokeMethod(obj, "addNumbers",
                                         Qt::QueuedConnection, // ? 異步調(diào)用
                                         Q_RETURN_ARG(int, result),
                                         Q_ARG(int, 3),
                                         Q_ARG(int, 5));

上面這段代碼會導(dǎo)致報(bào)錯(cuò):

QMetaMethod::invoke: Unable to invoke methods with return values in queued connections

正確做法

? 方法一:使用Qt::DirectConnection(同步調(diào)用)

如果你需要獲取返回值,請使用同步連接方式:

int result = 0;
bool success = QMetaObject::invokeMethod(obj, "addNumbers",
                                         Qt::DirectConnection, // ? 同步調(diào)用
                                         Q_RETURN_ARG(int, result),
                                         Q_ARG(int, 3),
                                         Q_ARG(int, 5));

if (success) {
    qDebug() << "Result:" << result;
}

?? 注意:Qt::DirectConnection 要求調(diào)用線程和目標(biāo)對象處于同一個(gè)線程,否則行為未定義。

? 方法二:避免返回值 + 使用信號傳遞結(jié)果(適合異步場景)

如果你確實(shí)需要跨線程調(diào)用并想獲取結(jié)果,可以這樣做:

步驟如下:

  1. 將原函數(shù)改為無返回值;
  2. 使用 QMetaObject::invokeMethod() 調(diào)用它;
  3. 函數(shù)內(nèi)部處理完后,發(fā)出一個(gè)信號把結(jié)果傳回來。

示例代碼:

class Worker : public QObject {
    Q_OBJECT

signals:
    void resultReady(int result); // 用于返回結(jié)果

public slots:
    void addNumbersAsync(int a, int b) {
        int result = a + b;
        emit resultReady(result); // 發(fā)送結(jié)果
    }
};
調(diào)用方式:
Worker* worker = new Worker();
worker->moveToThread(thread);

// 連接信號與槽來接收結(jié)果
connect(worker, &Worker::resultReady, this, [](int res) {
    qDebug() << "異步返回結(jié)果:" << res;
});

// 異步調(diào)用
QMetaObject::invokeMethod(worker, "addNumbersAsync",
                          Qt::QueuedConnection,
                          Q_ARG(int, 3),
                          Q_ARG(int, 5));

總結(jié)1

場景是否允許返回值推薦連接方式備注
同一線程調(diào)用,需返回值? 是Qt::DirectConnection可使用 Q_RETURN_ARG
跨線程調(diào)用,需返回值? 否? 不可用必須用信號傳遞結(jié)果
跨線程調(diào)用,不需要返回值? 是Qt::QueuedConnection正常使用

QMetaObject::invokeMethod()的返回值類型

bool QMetaObject::invokeMethod(QObject *obj, const char *member, Qt::ConnectionType type, QGenericReturnArgument ret, ...)

返回值說明:

  • 返回類型:bool
  • 返回值含義
    • true:表示方法成功調(diào)用。
    • false:表示方法調(diào)用失敗,可能原因包括:
      • 沒有找到名字匹配的方法(函數(shù)名錯(cuò)誤或未聲明為 Q_INVOKABLE 或 slot)。
      • 參數(shù)類型不匹配。
      • 對象已經(jīng)被刪除(懸空指針)。
      • 使用了 Qt::QueuedConnection 但目標(biāo)對象沒有運(yùn)行事件循環(huán)。

如何進(jìn)一步排查失敗原因?

雖然返回值只能告訴你是否成功,但你可以通過以下方式定位問題:

1. 檢查函數(shù)是否被正確聲明為Q_INVOKABLE或slot

class Worker : public QObject {
    Q_OBJECT

public slots:
    void OpenPort(const QString &portName, int baudRate); // 必須匹配參數(shù)類型
};

或者:

Q_INVOKABLE void OpenPort(const QString &portName, int baudRate);

2. 確保對象沒有被釋放(避免懸空指針)

確保 m_pWork 是一個(gè)有效的 QObject* 指針,且對象尚未被 delete。

3. 參數(shù)類型必須一致(支持元對象系統(tǒng))

確保你使用的參數(shù)類型是 Qt 元對象系統(tǒng)支持的類型(如 int, QString, double 等),或者自定義類型已注冊:

Q_DECLARE_METATYPE(MyCustomType)
qRegisterMetaType<MyCustomType>();

4. 調(diào)試輸出所有可用方法(用于排查函數(shù)名/參數(shù)是否正確)

const QMetaObject* metaObj = m_pWork->metaObject();
for (int i = 0; i < metaObj->methodCount(); ++i) {
    qDebug() << metaObj->method(i).signature();
}

總結(jié)2

內(nèi)容說明
invokeMethod() 是否有返回值?? 有,返回 bool 類型
true 表示什么?方法調(diào)用成功
false 表示什么?方法調(diào)用失敗(函數(shù)名錯(cuò)誤、參數(shù)不匹配、對象無效、異步調(diào)用等)
可以用來做什么?判斷函數(shù)是否被成功調(diào)用,用于調(diào)試和錯(cuò)誤處理

到此這篇關(guān)于判斷QMetaObject::invokeMethod()里的函數(shù)是否調(diào)用成功的文章就介紹到這了,更多相關(guān)QMetaObject::invokeMethod()調(diào)用內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家! 

相關(guān)文章

  • C語言實(shí)現(xiàn)Fibonacci數(shù)列遞歸

    C語言實(shí)現(xiàn)Fibonacci數(shù)列遞歸

    這篇文章主要介紹了C語言實(shí)現(xiàn)Fibonacci數(shù)列遞歸,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-02-02
  • C語言sizeof和strlen區(qū)別小結(jié)

    C語言sizeof和strlen區(qū)別小結(jié)

    C語言中的sizeof和strlen是兩個(gè)常用的操作符/函數(shù),但它們的功能和用途有很大的區(qū)別,本文就詳細(xì)的來介紹一下C語言sizeof和strlen區(qū)別,具有一定的參考價(jià)值,感興趣的可以了解一下
    2024-01-01
  • C++變量存儲的生命周期與作用域?qū)嵗a精講

    C++變量存儲的生命周期與作用域?qū)嵗a精講

    這篇文章主要介紹了C++變量存儲的生命周期與作用域,從創(chuàng)建到消亡的完整過程,例如人從出生到死亡的整個(gè)過程就是一個(gè)生命周期。本文將通過示例為大家詳細(xì)講講,感興趣的可以學(xué)習(xí)一下
    2022-10-10
  • C語言在頭文件中定義const變量詳解

    C語言在頭文件中定義const變量詳解

    這篇文章主要介紹了C語言在頭文件中定義const變量詳解的相關(guān)資料,需要的朋友可以參考下
    2017-05-05
  • C語言圖書借閱系統(tǒng)源碼

    C語言圖書借閱系統(tǒng)源碼

    這篇文章主要為大家分享了C語言圖書借閱系統(tǒng)源碼,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-02-02
  • VC++ 自定義控件的建立及使用方法

    VC++ 自定義控件的建立及使用方法

    這篇文章主要介紹了VC++ 自定義控件的建立及使用方法的相關(guān)資料,十分的詳細(xì),需要的朋友可以參考下
    2015-06-06
  • c語言中assert斷言用法實(shí)例詳解

    c語言中assert斷言用法實(shí)例詳解

    斷言是C語言中一種用于檢查程序中假設(shè)語句正確性的方法,通過使用斷言,開發(fā)人員可以在程序中插入一些條件,以確保程序的執(zhí)行滿足特定的預(yù)期,這篇文章主要給大家介紹了關(guān)于c語言中assert斷言用法的相關(guān)資料,需要的朋友可以參考下
    2024-02-02
  • Qt的Qss用法小結(jié)

    Qt的Qss用法小結(jié)

    Qt的Qss是一種用于定義用戶界面的樣式表語言,本文主要介紹了Qt的Qss用法小結(jié),非常具有實(shí)用價(jià)值,需要的朋友可以參考下
    2023-06-06
  • VC++?2019?"const?char*"類型的實(shí)參與"LPCTSTR"類型的形參不兼容解決

    VC++?2019?"const?char*"類型的實(shí)參與"LPCTSTR"

    這篇文章主要給大家介紹了關(guān)于VC++?2019?"const?char*"類型的實(shí)參與"LPCTSTR"類型的形參不兼容的解決方法,文中通過圖文介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2023-03-03
  • c++輸出斐波那契數(shù)列示例分享

    c++輸出斐波那契數(shù)列示例分享

    這篇文章主要介紹了c++輸出斐波那契數(shù)列示例,需要的朋友可以參考下
    2014-03-03

最新評論

宣汉县| 海兴县| 杂多县| 安国市| 红河县| 靖西县| 波密县| 黑水县| 淮滨县| 红安县| 昌宁县| 宣城市| 克拉玛依市| 绥江县| 南宁市| 濮阳县| 威海市| 大安市| 遂宁市| 峡江县| 环江| 新闻| 土默特右旗| 聂拉木县| 黎川县| 银川市| 乐业县| 自治县| 柘荣县| 湘阴县| 崇信县| 苏尼特左旗| 瓮安县| 绵阳市| 海南省| 郧西县| 横峰县| 五寨县| 军事| 淳化县| 竹北市|