Qt moveToThread () против вызова нового потока, когда мы используем каждый - PullRequest
7 голосов
/ 01 марта 2011

Когда мы используем каждый из этих вызовов функций в многопоточном приложении.даны две функции fun1 () и fun2 (), определенные в одном классе, занимающиеся чтением / записью данных в буферы (операция очереди).для достижения многопоточности к этим.мы должны были бы запустить две функции в отдельном потоке.Теперь предположим, что первая функция read вызывается в начале своего потока.

лучше ли использовать moveTothread (второй поток) для записи функции в начале первого потока функций

Или

определяют вторую функцию в новом классе потоков и вызывают этот поток в начале первого потока.

Ответы [ 2 ]

9 голосов
/ 01 марта 2011

Как ответил Петр, вы действительно должны взглянуть на предложенную им ссылку.
Насколько я понимаю, ваша проблема должна решить вашу проблему.
Это упрощенный код из этого блога:

class Producer  
{  
public:
    Producer();  

public slots:
    void produce()
    { //do whatever to retrieve the data
      //and then emit a produced signal with the data
      emit produced(data);
      //if no more data, emit a finished signal
      emit finished();
    }

signals:
    void produced(QByteArray *data);
    void finished();
};

class Consumer
{
public:
    Consumer();

public slots:
    void consume(QByteArray *data)
    {
       //process that data
       //when finished processing emit a consumed signal
       emit consumed();
       //if no data left in queue emit finished
       emit finished();
    }
};

int main(...)
{
    QCoreApplication app(...);

    Producer producer;
    Consumer consumer;

    producer.connect(&consumer, SIGNAL(consumed()), SLOT(produce()));
    consumer.connect(&producer, SIGNAL(produced(QByteArray *)), SLOT(consume(QByteArray *));

    QThread producerThread;
    QThread consumerThread;
    producer.moveToThread(&producerThread);
    consumer.moveToThread(&consumerThread);

    //when producer thread is started, start to produce
    producer.connect(&producerThread, SIGNAL(started()), SLOT(produce()));

    //when consumer and producer are finished, stop the threads
    consumerThread.connect(&consumer, SIGNAL(finished()), SLOT(quit()));
    producerThread.connect(&producer, SIGNAL(finished()), SLOT(quit()));

    producerThread.start();
    consumerThread.start();

    return app.exec();
}
8 голосов
/ 21 ноября 2011

Используя moveToThread, мы можем изменить сродство потока объекта. ОП спрашивает, как мы можем запустить две функции одного класса в разных потоках.

Пусть класс A и две функции f1 и f2

class A
{
public:
    void f1();
    void f2(int i); 
    void run(); // shows how we can trigger f1 and f2 in different threads
}

Qt уже предоставил класс для запуска функций в разных потоках, и он называется QtConcurrentRun

Функция QtConcurrent::run() запускает функцию в отдельном потоке. Возвращаемое значение функции доступно через QFuture API.

Срабатывающая функция может быть либо внешней, либо функцией-членом. Так что в нашем случае, если бы мы хотели, чтобы из самого объекта запускались f1 и f2 в разных потоках, мы могли бы сделать следующее в run()

void run()
{
   // QFuture<void> because f1 is void 
   QFuture<void> future1 = QtConcurrent::run(this, &A::f1);
   int k = 5; // Concurrent run with arguments
   QFuture<void> future2 = QtConcurrent::run(this, &A::f2, k);
} 

аналогично, вы можете выполнять любую публичную функцию любого класса одновременно, например,

QImage image = ...;
QFuture<void> future = QtConcurrent::run(image, &QImage::invertPixels, QImage::InvertRgba);

A a;
QFuture<void> future1 = QtConcurrent::run(A, &A::f1);

Обратите внимание на разницу между двумя вызовами:

QtConcurrent::run() также принимает указатели на функции-члены. Первый аргумент должен быть либо константной ссылкой, либо указателем на экземпляр класса. Передача по константной ссылке полезна, когда вызов константных функций-членов; передача по указателю полезна для вызов неконстантных функций-членов, которые изменяют экземпляр.

Чтобы проверить, когда одновременно выполненная функция завершена, вы должны использовать QFutureWatcher.

...