久久久久久久av_日韩在线中文_看一级毛片视频_日本精品二区_成人深夜福利视频_武道仙尊动漫在线观看

在 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 ()?環形?)
主站蜘蛛池模板: www.日韩系列 | 国产一区二区精品 | 久久精品国产一区二区三区不卡 | 日韩激情一区 | 亚洲国产精品一区 | 蜜臀av日日欢夜夜爽一区 | 天天操夜夜看 | 国产永久免费 | 一区二区高清不卡 | 亚洲午夜精品 | 一区二区在线不卡 | 精品一区二区三区四区在线 | 欧美网站一区二区 | 91精品国产91久久久久久 | 影音先锋中文在线 | 日韩免费看视频 | 电影午夜精品一区二区三区 | 国产精品1区2区3区 一区中文字幕 | 国产一区91在线 | 午夜激情一区 | 伊人春色成人网 | 91一区二区三区在线观看 | 天堂一区二区三区 | 九九国产在线观看 | 国产亚洲一区二区三区 | 91免费入口| 午夜影院 | 成人精品在线观看 | 国产精品久久久久久久久久久免费看 | 国产资源在线观看 | 日日干夜夜操天天操 | 亚洲av毛片成人精品 | 精品乱码一区二区 | 阿v视频在线观看 | 午夜精品一区二区三区在线观看 | 欧美一区二区三区在线观看 | 久久久久国产 | 99在线免费观看视频 | 国产精品一区二区视频 | 免费精品视频 | 国产精品免费av |