pbootcms网站模板|日韩1区2区|织梦模板||网站源码|日韩1区2区|jquery建站特效-html5模板网

在 Qt 中使用排隊連接時如何壓縮插槽調用?

How to Compress Slot Calls When Using Queued Connection in Qt?(在 Qt 中使用排隊連接時如何壓縮插槽調用?)
本文介紹了在 Qt 中使用排隊連接時如何壓縮插槽調用?的處理方法,對大家解決問題具有一定的參考價值,需要的朋友們下面隨著小編來一起學習吧!

問題描述

在閱讀了一些關于 Qt Signal-Slot 通信的文章像這樣后,我仍然有關于排隊連接的問題.

After reading some articles like this about Qt Signal-Slot communications I still have a question concerning the queued connection.

如果我有一些線程一直在互相發送信號,并且假設一個 thread_slow 在它的事件循環中運行一個慢速方法而另一個 thread_fast 正在運行一個快速發送多個信號而另一個線程仍在運行它的慢方法.....當來自 thread_slow 的慢方法返回到事件循環時,它會處理之前發送的所有信號通過 thread_fast 還是只是最后一個(所有信號都是相同的類型)?

If I have some threads sending signals all the time to each other and lets say one thread_slowis running a slow method in it's event loop and another thread_fast is running a fast one that sends multiple signals while the other thread is still running it's slow method.....when the slow method from thread_slow returns to the event loop, will it process all the signals that were sent before by thread_fastor just the last one (all the signals are the same type)?

如果它會處理所有的信號,有沒有辦法讓thread_slow 只處理最后一個?(考慮到多線程應用程序中的最后一個"可能含糊不清,為了簡單起見,讓我們考慮線程請求最后一個信號之前的最后一個信號,因此在線程尋找最后一個信號時發送的新信號可能會丟失).

If it will process all the signals, is it there a way to make the thread_slow only process the last one? (Considering "the last one" in a multithread application might be vague, let's consider the last signal before the thread asked for the last signal, for the sake of simplicity, so new ones being sent while the thread looks for the last might be lost).

(我問這個是因為我有多個線程從多個線程接收數據,我不希望它們處理舊數據,只是發送的最后一個)

(I am asking this because I have multiple threads receiving data from multiple threads, and I dont want them to process old data, just the last one that was sent)

我已經運行了一些測試,似乎 Qt 會處理所有信號.我做了一個線程:

I have run some tests, and it appears that Qt will process all the signals. I made one thread do:

while(true)
{
    QThread::msleep(500);
    emit testQueue(test);
    test++;
}

另一個插槽可以:

void test::testQueue(int test)
{
    test.store(private_test.load() + test);
    emit testText(QString("Test Queue: ") + QString::number(private_test.load()));
}

線程將運行:

while(true)
{
    QThread::msleep(3000);
    QCoreApplication::processEvents();
    private_test.store(private_test.load() + 1000);
}

我每 500 毫秒從一個線程向另一個線程發送一個信號,另一個線程休眠 3000 毫秒(3 秒),然后喚醒并將內部變量增加 100.每次執行插槽時,它都會發出帶有接收值 + 內部變量的文本.我得到的結果是每次 QCoreApplication::processEvents(); 被調用時,所有的信號都會被執行....(我編輯了這部分是因為我在之前的代碼中發現了一個錯誤)

I am sending a signal from one thread to the other every 500 milliseconds, and the other thread sleeps for 3000 milliseconds (3 seconds) and then wakes up and increment an internal variable by 100. every time the slot is executed it emits a text with the value received + the internal variable. The result I am having is that every time QCoreApplication::processEvents(); is called, all signals are executed....(I edited this part because I found a bug in my previous code)

推薦答案

我正在嘗試將我的評論轉化為答案.我同意您的觀點,即文檔中缺少這些信息,或者至少對我來說不清楚,顯然對您來說也是如此.

I am trying to form my comment into an answer. I agree with you about that the documentation is lacking this information, or at least it is not clear for me, and apparently for you either.

獲取更多信息有兩種選擇:

There would be two options to get more information:

1) 試用

將 qDebug() 或 printf()/fprintf() 語句放入慢"線程中的插槽中,然后查看打印出的內容.運行幾次并得出結論.

Put a qDebug() or printf()/fprintf() statement into your slot in the "slow" thread and see what it prints out. Run this a few times and draw the conclusion.

2) 確保

您需要閱讀元對象編譯器的源代碼,也就是.moc 從源文件中獲取此信息.這是一個更復雜的調查,但這可能會導致確定性.

You would need to read the source code for this how the meta object compiler, aka. moc gets this through from the source file. This is a bit more involved investigation, but this could lead to certainity.

據我所知,每個信號發射都會發布一個相應的事件.然后,該事件將排隊等待線程類中的單獨線程.在這里可以找到相關的兩個源代碼文件:

As far as I know, every signal emission posting a corresponding event. Then, the event will be queued for the separate thread within the thread class. Here you can find the relevant two source code files:

void QCoreApplication::postEvent(QObject *receiver, QEvent *event, int priority)

class public QPostVEventListector/a>

class QPostEventList : public QVector

有兩種權衡方法:

主要優點是在忙操作期間信號不會丟失.但是,這本身可能會較慢,因為它可能會處理比需要更多的操作.

The main advantage is that signals could not be lost during the busy operation. However, this could be inherently slower as it can potentially process a lot more operation than needed.

這個想法是為每個處理的事件重新設置數據,但真正的繁忙操作只排隊執行一次.如果有更多事件,它不一定是第一個事件,但這是最簡單的實現.

The idea is that the data is re-set for each event handled, but the real busy operation is queued for execution only once. It does not necessarily have to be the for the first event if there are more, but that is the simplest implementation.

Foo::Foo(QObject *parent) : QObject(parent)
{
    ...
    connect(this, SIGNAL(dataUpdateSignal(const QByteArray&)), SLOT(dataUpdateSlot(const QByteArray&)));
    connect(this, SIGNAL(queueBusyOperationSignal()), SLOT(busyOperation()));
    ...
}

void Foo::dataUpdateSlot(const QByteArray &data)
{
    m_data = data;

    if (busyOperationQueued);
        emit queueBusyOperationSignal();
        m_busyOperationQueued = true;
    }
}

void MyClass::busyOperationSlot()
{

    // Do the busy work with m_data here

    m_busyOperationQueued = false;    
}

連接/斷開連接

思路是在開始處理的時候,把slot和對應的信號斷開.這將確保不會捕獲新的信號發射,并在線程有空處理下一個事件時再次將槽連接到信號.

Connect/Disconnect

The idea is to disconnect the slot from the corresponding signal when starting the processing. This will ensure that new signal emission would not be caught, and connect the slot to the signal again once the thread is free to process the next events.

盡管在連接和下一個偶數處理之間,這將在線程中有一些空閑時間,但至少這將是實現它的簡單方法.根據此處未真正提供的更多上下文,性能差異實際上甚至可以忽略不計.

This would have some idle time in the thread though between the connection and the next even handled, but at least this would be a simple way of implmeneting it. It may actually be even negligible a performance difference depending on more context not really provided here.

主要缺點是這會在繁忙操作期間丟失信號.

The main drawback is that this would lose the signals during the busy operation.

Foo::Foo(QObject *parent) : QObject(parent)
{
    ...
    connect(this, SIGNAL(dataUpdateSignal(const QByteArray&)), SLOT(busyOperationSlot(const QByteArray&)));
    ...
}

void MyClass::busyOperationSlot(const QByteArray &data)
{
    disconnect(this, SIGNAL(dataUpdateSignal(const QByteArray&)), this, SLOT(dataUpdateSlot(const QByteArray&)));

    // Do the busy work with data here

    connect(this, SIGNAL(dataUpdateSignal(const QByteArray&)), SLOT(dataUpdateSlot(const QByteArray&)));
}

未來的想法

我在想是否有一個方便的 API - 例如一個 processEvents() 類似的方法,但有一個參數來處理最后一個發布的事件 - 實際上明確地告訴事件系統處理最后一個而不是繞過問題本身.它看起來確實是這樣的 API,但它是私有的.

Future thoughts

I was thinking if there was a convenient API - e.g. a processEvents() alike method, but with an argument to process only the last event posted - for actually telling the event system explicitly to process the last one rather than circumventing the issue itself. It does appear to be such an API, however, it is private.

也許,有人會提交功能請求以公開發布類似內容.

Perhaps, someone will submit a feature request to have something like that in public.

/*!
internal
Returns c true if a event was compressed away (possibly deleted) and should not be added to the list.
*/
bool QCoreApplication::compressEvent(QEvent *event, QObject *receiver, QPostEventList *postedEvents)

相關源碼可在這里.

它似乎在 QGuiApplicationQApplication 中也有一個覆蓋版本.

It also seems to have an overriden version in QGuiApplication and QApplication.

至于完整性,還有這樣的方法:

As for completeness, there is also such a method like this:

void QCoreApplication::removePostedEvents(QObject *receiver, int eventType = 0) [靜態]

刪除使用 postEvent() 作為接收者發布的給定 eventType 的所有事件.

Removes all events of the given eventType that were posted using postEvent() for receiver.

事件不會被調度,而是從隊列中移除.您永遠不需要調用此函數.如果您調用它,請注意終止事件可能會導致接收器破壞一個或多個不變量.

The events are not dispatched, instead they are removed from the queue. You should never need to call this function. If you do call it, be aware that killing events may cause receiver to break one or more invariants.

如果接收者為空,則所有對象的 eventType 事件都會被移除.如果 eventType 為 0,則為接收器刪除所有事件.永遠不要在 eventType 為 0 的情況下調用此函數.如果確實以這種方式調用它,請注意殺死事件可能會導致接收器破壞一個或多個不變量.

If receiver is null, the events of eventType are removed for all objects. If eventType is 0, all the events are removed for receiver. You should never call this function with eventType of 0. If you do call it in this way, be aware that killing events may cause receiver to break one or more invariants.

但是根據文檔,這并不是您想要的.

But this is not quite what you would like to have here as per documentation.

這篇關于在 Qt 中使用排隊連接時如何壓縮插槽調用?的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網!

【網站聲明】本站部分內容來源于互聯網,旨在幫助大家更快的解決問題,如果有圖片或者內容侵犯了您的權益,請聯系我們刪除處理,感謝您的支持!

相關文檔推薦

How can I read and manipulate CSV file data in C++?(如何在 C++ 中讀取和操作 CSV 文件數據?)
In C++ why can#39;t I write a for() loop like this: for( int i = 1, double i2 = 0; (在 C++ 中,為什么我不能像這樣編寫 for() 循環: for( int i = 1, double i2 = 0;)
How does OpenMP handle nested loops?(OpenMP 如何處理嵌套循環?)
Reusing thread in loop c++(在循環 C++ 中重用線程)
Precise thread sleep needed. Max 1ms error(需要精確的線程睡眠.最大 1ms 誤差)
Is there ever a need for a quot;do {...} while ( )quot; loop?(是否需要“do {...} while ()?環形?)
主站蜘蛛池模板: 中空玻璃生产线,玻璃加工设备,全自动封胶线,铝条折弯机,双组份打胶机,丁基胶/卧式/立式全自动涂布机,玻璃设备-山东昌盛数控设备有限公司 | 青岛侦探_青岛侦探事务所_青岛劝退小三_青岛调查出轨取证公司_青岛婚外情取证-青岛探真调查事务所 | 郑州水质检测中心_井水检测_河南废气检测_河南中环嘉创检测 | 筒瓦厂家-仿古瓦-寺庙-古建琉璃瓦-宜兴市古典园林建筑陶瓷厂有限公司 | 学考网学历中心| 电动球阀_不锈钢电动球阀_电动三通球阀_电动调节球阀_上海湖泉阀门有限公司 | 电动百叶窗,开窗器,电动遮阳百叶,电动开窗机生产厂家-徐州鑫友工控科技发展有限公司 | 隧道窑炉,隧道窑炉厂家-山东艾瑶国际贸易 | 液压中心架,数控中心架,自定心中心架-烟台恒阳机电设计有限公司 行星搅拌机,双行星搅拌机,动力混合机,无锡米克斯行星搅拌机生产厂家 | 原色会计-合肥注册公司_合肥代理记账公司_营业执照代办 | 代理记账_免费注册公司_营业执照代办_资质代办-【乐财汇】 | 河南橡胶接头厂家,河南波纹补偿器厂家,河南可曲挠橡胶软连接,河南套筒补偿器厂家-河南正大阀门 | 天津力值检测-天津管道检测-天津天诚工程检测技术有限公司 | 氧化铝球_高铝球_氧化铝研磨球-淄博誉洁陶瓷新材料有限公司 | 考勤系统_人事考勤管理系统_本地部署BS考勤系统_考勤软件_天时考勤管理专家 | 氧化铁红厂家-淄博宗昂化工 | 作文导航网_作文之家_满分作文_优秀作文_作文大全_作文素材_最新作文分享发布平台 | 对辊式破碎机-对辊制砂机-双辊-双齿辊破碎机-巩义市裕顺机械制造有限公司 | 电动手术床,医用护理床,led手术无影灯-曲阜明辉医疗设备有限公司 | 东莞动力锂电池保护板_BMS智能软件保护板_锂电池主动均衡保护板-东莞市倡芯电子科技有限公司 | 吹塑加工_大型吹塑加工_滚塑代加工-莱力奇吹塑加工有限公司 | 精密模具-双色注塑模具加工-深圳铭洋宇通 | 杭州用友|用友软件|用友财务软件|用友ERP系统--杭州协友软件官网 | 帽子厂家_帽子工厂_帽子定做_义乌帽厂_帽厂_制帽厂_帽子厂_浙江高普制帽厂 | 广东风淋室_广东风淋室厂家_广东风淋室价格_广州开源_传递窗_FFU-广州开源净化科技有限公司 | 南京试剂|化学试剂|分析试剂|实验试剂|cas号查询-专业60年试剂销售企业 | 急救箱-应急箱-急救包厂家-北京红立方医疗设备有限公司 | 桂林腻子粉_内墙外墙抗裂砂浆腻子粉推荐广西鑫达涂料厂家供应 | 包装设计公司,产品包装设计|包装制作,包装盒定制厂家-汇包装【官方网站】 | 复合土工膜厂家|hdpe防渗土工膜|复合防渗土工布|玻璃纤维|双向塑料土工格栅-安徽路建新材料有限公司 | 净水器代理,净水器招商,净水器加盟-FineSky德国法兹全屋净水 | CTAB,表面活性剂1631溴型(十六烷基三甲基溴化铵)-上海升纬化工原料有限公司 | 蒜肠网-动漫,二次元,COSPLAY,漫展以及收藏型模型,手办,玩具的新媒体.(原变形金刚变迷TF圈) | 滚珠丝杆升降机_螺旋升降机_丝杠升降机-德迈传动 | 二手光谱仪维修-德国OBLF光谱仪|进口斯派克光谱仪-热电ARL光谱仪-意大利GNR光谱仪-永晖检测 | 淄博不锈钢,淄博不锈钢管,淄博不锈钢板-山东振远合金科技有限公司 | led太阳能路灯厂家价格_风光互补庭院灯_农村市政工程路灯-中山华可路灯品牌 | 旅游规划_旅游策划_乡村旅游规划_景区规划设计_旅游规划设计公司-北京绿道联合旅游规划设计有限公司 | 专业广州网站建设,微信小程序开发,一物一码和NFC应用开发、物联网、外贸商城、定制系统和APP开发【致茂网络】 | 不锈钢管件(不锈钢弯头,不锈钢三通,不锈钢大小头),不锈钢法兰「厂家」-浙江志通管阀 | 粘度计,数显粘度计,指针旋转粘度计 |