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

Qt線程之間發送大量數據

Sending large amount of data between Qt threads(Qt線程之間發送大量數據)
本文介紹了Qt線程之間發送大量數據的處理方法,對大家解決問題具有一定的參考價值,需要的朋友們下面隨著小編來一起學習吧!

問題描述

我有一個 QThread,它會定期生成大量數據(每秒幾兆字節),并且需要將其傳輸到父 (GUI) 線程.

I have a QThread which generates a fairly large amount of data regularly (couple of megabytes per second), and it needs to transmit it to the parent (GUI) thread.

恐怕我對 QThread 的內部運作不是很確定,所以我想尋求最佳實踐.

I'm afraid I'm not that certain in the inner workings of QThread so I would like to ask for a best practice.

顯然,傳輸數據最直接的方式就是emit一個數組.然而,這有多有效?Qt是否知道它的使用位置并避免在發送和接收時進行深度復制?

Obviously, the most direct way to transmit data is to just emit an array. However, how efficient is this? Does Qt know about where it is used and avoids deep copying it when sending and receiving it?

如果沒有,我很樂意只在主線程中分配內存并提供一個指向子線程的指針,它將在其中寫入數據(并且只emit關于進度的短消息).這對我來說似乎不是最優雅的解決方案,這就是我問的原因.

If not, I can gladly just allocate the memory in the main thread and give a pointer to the child thread where it will write the data (and only emit short messages about the progress). This does not seem to be the most elegant solution to me, this is why I'm asking.

如果Qt在發送和接收時避免復制多個緩沖區中的數據,是否在所有系統中都能保證?我沒有資源嘗試在各種操作系統下對其進行基準測試.

If Qt avoids copying the data in multiple buffers when emitting and receiving, is it guaranteed in all systems? I don't have the resources to try benchmarking it under various OSs.

推薦答案

QThread 的內部工作無關緊要:它們在事件循環的工作方式中沒有任何作用.當您在 QObject發出一個信號,該信號位于與插槽對象不同的線程中時,該信號將作為 QMetaCallEvent 發布到接收線程的事件隊列.然后,在接收線程中運行的事件循環將對該事件執行操作,并在連接到所發出信號的槽中執行調用.

QThread's inner workings are irrelevant: they play no role in how the event loops work. When you emit a signal in a QObject that lives in a thread different from the slot's object, the signal will be posted as a QMetaCallEvent to the event queue of the receiving thread. The event loop running in the receiving thread will then act on this event and execute the call into the slot that was connected to the emitted signal.

因此,無論發生什么,您通過信號發送的任何數據最終都將作為 QEvent 派生類實例中的有效負載結束.

So, no matter what happens, whatever data you send through the signal will eventually end up as a payload in an instance of QEvent-derived class.

問題的關鍵在于當 QMetaCallEvent 到達事件循環并且容器作為參數被傳遞到槽中時.當然,復制構造函數可以在此過程中多次調用.下面是一些簡單的代碼,演示了復制構造函數和默認構造函數實際上被調用了多少次

The meat of the issue is when the QMetaCallEvent reaches the event loop and the container gets passed into the slot as an argument. Of course the copy constructors could be called plenty of times along the way. Below is some simple code that demonstrates how many times the copy constructor and default constructor are in fact called

  • 關于隱式共享的寫時復制容器 (QVector) 的數據成員的元素,

  • on the elements of the data members of an implicitly shared copy-on-write container (QVector),

在代表容器的自定義類上.

on a custom class that stands in for a container.

你會驚喜的 :)

由于 Qt 容器是隱式共享的寫時復制,因此它們的復制構造成本可以忽略不計:所做的只是引用計數器在構造時自動遞增.例如,不會復制任何數據成員.

Since Qt containers are implicitly shared copy-on-write, their copy construction has negligible cost: all that's done is a reference counter is incremented atomically on construction. None of the data members are copied, for example.

唉,11 歲之前的 C++ 顯示了它丑陋的一面:如果槽代碼以任何方式修改了容器,則無法以這種方式傳遞對槽的引用,讓編譯器知道原始容器不是不再需要了.因此:如果插槽收到對容器的 const 引用,則可以保證不會制作任何副本.如果槽接收到容器的可寫副本并且你修改了它,將會有一個完全不必要的副本,因為調用站點上的實例不再需要.在 C++-11 中,您將傳遞一個右值引用作為參數.在函數調用中傳遞右值引用會結束調用者中傳遞對象的生命周期.

Alas, pre-11 C++ shows its ugly side: if the slot code modifies the container in any way, there's no way to pass references to the slot in such a way that would let the compiler know that the original container is not needed anymore. Thus: if the slot receives a const reference to the container, you're guaranteed that no copies will be made. If the slot receives a writeable copy of the container and you modify it, there will be a completely unnecessary copy made since the instance alive at the call site is no longer needed. In C++-11 you'd pass an rvalue reference as a parameter. Passing an rvalue reference in a function call ends the lifetime of the passed object in the caller.

示例代碼輸出:

"Started" copies: 0 assignments: 0 default instances: 0 
"Created Foo" copies: 0 assignments: 0 default instances: 100 
"Created Bar" copies: 0 assignments: 0 default instances: 100 
"Received signal w/const container" copies: 0 assignments: 0 default instances: 100 
"Received signal w/copy of the container" copies: 0 assignments: 0 default instances: 100 
"Made a copy" copies: 100 assignments: 1 default instances: 101 
"Reset" copies: 0 assignments: 0 default instances: 0 
"Received signal w/const class" copies: 2 assignments: 0 default instances: 1 
"Received signal w/copy of the class" copies: 3 assignments: 0 default instances: 1 

//main.cpp
#include <QtCore>

class Class {
    static QAtomicInt m_copies;
    static QAtomicInt m_assignments;
    static QAtomicInt m_instances;
public:
    Class() { m_instances.fetchAndAddOrdered(1); }
    Class(const Class &) { m_copies.fetchAndAddOrdered(1); }
    Class & operator=(const Class &) { m_assignments.fetchAndAddOrdered(1); return *this; }
    static void dump(const QString & s = QString()) {
        qDebug() << s << "copies:" << m_copies << "assignments:" << m_assignments << "default instances:" << m_instances;
    }
    static void reset() {
        m_copies = 0;
        m_assignments = 0;
        m_instances = 0;
    }
};

QAtomicInt Class::m_instances;
QAtomicInt Class::m_copies;
QAtomicInt Class::m_assignments;

typedef QVector<Class> Vector;

Q_DECLARE_METATYPE(Vector)

class Foo : public QObject
{
    Q_OBJECT
    Vector v;
public:
    Foo() : v(100) {}
signals:
    void containerSignal(const Vector &);
    void classSignal(const Class &);
public slots:
    void sendContainer() { emit containerSignal(v); }
    void sendClass() { emit classSignal(Class()); }
};

class Bar : public QObject
{
    Q_OBJECT
public:
    Bar() {}
signals:
    void containerDone();
    void classDone();
public slots:
    void containerSlotConst(const Vector &) {
        Class::dump("Received signal w/const container");
    }
    void containerSlot(Vector v) {
        Class::dump("Received signal w/copy of the container");
        v[99] = Class();
        Class::dump("Made a copy");
        Class::reset();
        Class::dump("Reset");
        emit containerDone();
    }
    void classSlotConst(const Class &) {
        Class::dump("Received signal w/const class");
    }
    void classSlot(Class) {
        Class::dump("Received signal w/copy of the class");
        emit classDone();
        //QThread::currentThread()->quit();
    }
};

int main(int argc, char ** argv)
{
    QCoreApplication a(argc, argv);
    qRegisterMetaType<Vector>("Vector");
    qRegisterMetaType<Class>("Class");

    Class::dump("Started");
    QThread thread;
    Foo foo;
    Bar bar;
    Class::dump("Created Foo");
    bar.moveToThread(&thread);
    Class::dump("Created Bar");
    QObject::connect(&thread, SIGNAL(started()), &foo, SLOT(sendContainer()));
    QObject::connect(&foo, SIGNAL(containerSignal(Vector)), &bar, SLOT(containerSlotConst(Vector)));
    QObject::connect(&foo, SIGNAL(containerSignal(Vector)), &bar, SLOT(containerSlot(Vector)));
    QObject::connect(&bar, SIGNAL(containerDone()), &foo, SLOT(sendClass()));
    QObject::connect(&foo, SIGNAL(classSignal(Class)), &bar, SLOT(classSlotConst(Class)));
    QObject::connect(&foo, SIGNAL(classSignal(Class)), &bar, SLOT(classSlot(Class)));
    QObject::connect(&bar, SIGNAL(classDone()), &thread, SLOT(quit()));
    QObject::connect(&thread, SIGNAL(finished()), &a, SLOT(quit()));
    thread.start();
    a.exec();
    thread.wait();
}

#include "main.moc"

這篇關于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 ()?環形?)
主站蜘蛛池模板: 国产亚洲精品区 | 国产中文区二幕区2012 | 欧美性影院 | 一区二区不卡视频 | 国产精品日韩高清伦字幕搜索 | 国产精品日韩在线 | 日韩精品一区二区在线观看 | 国产欧美日韩一区二区三区在线 | 7777久久 | 日韩一区中文字幕 | 成人av一区| 二区在线视频 | 国产激情综合五月久久 | 日韩一二三区视频 | 日韩三级在线观看 | 成人欧美一区二区三区黑人孕妇 | 黑人一级片视频 | a久久 | 成人在线观看免费视频 | 成人在线a | 亚洲 欧美 另类 综合 偷拍 | 中文字幕av一区二区三区 | 欧美爱爱视频网站 | 国产精品日日摸夜夜添夜夜av | 91av国产在线视频 | av天天澡天天爽天天av | 欧美日韩精品一区二区三区视频 | 韩国成人在线视频 | 国产一区二区电影 | 黄 色 毛片免费 | 国产精品久久久久aaaa | 欧美一级片在线 | 国产激情一区二区三区 | 国产高潮好爽受不了了夜色 | 免费一区在线观看 | 九九久久精品 | 中文字幕在线一区二区三区 | 欧美在线一二三 | 亚洲乱码一区二区三区在线观看 | jizz在线看片 | 日韩在线视频一区 |