Запуск отдельного процесса или потока в Qt - PullRequest
8 голосов
/ 29 мая 2009

Я пишу свое первое правильное полезное программное обеспечение. Частично это будет связано с просмотром изображения пользователем и принятием или отклонением. Это приведет к тому, что изображение будет сохранено в принятой или отклоненной папке и, возможно, повернуто и / или изменено в размере.

В данный момент моя операция поворота / изменения размера / сохранения приостанавливает выполнение моей программы, но я бы хотел, чтобы это происходило в фоновом режиме, чтобы следующее изображение отображалось немедленно.

Это единственный способ сделать это в Qt для обработки изображения в отдельном потоке, или есть другой способ? Я все еще разбираюсь в C ++ и Qt, так что я не хочу путать себя, погружаясь в новое поле!

Ответы [ 5 ]

14 голосов
/ 29 мая 2009

Qt имеет поддержку потоков. это пример приложения может показаться интересным, поскольку оно несколько похоже на то, что вы описываете.

Также, вот полная документация по потоку Qt .

3 голосов
/ 29 мая 2009

эти задачи идеально подходят для потоков. тем не менее, вы должны сначала выполнить «нормальную» функцию, которая это делает, и, когда она заработает, добавить поток, который читает очередь и вызывает ту же функцию обработки.

В Qt есть много инструментов, которые помогут вам в этом, в основном тот факт, что большинство контейнеров являются поточно-ориентированными, а также пара алгоритмов потоков (например, map-reduction). Тем не менее, сначала попробуйте синхронно.

2 голосов
/ 29 мая 2009

Отредактированный

Извините, ребята, мне очень трудно связать "Пример пользовательского типа в очереди" с требованиями.

Насколько я могу судить по вопросу, после того, как пользователь принял или отклонил изображение, оно должно быть необязательно повернуто и / или масштабировано и всегда сохранено в определенном каталоге и перейти к следующему изображению. (-> больше не взаимодействует с пользователем)
Даже если пользователь покидает текущий диалог, изображение все равно необходимо сохранить.

«Пример пользовательского типа в очереди» обрабатывает только одно изображение, всегда связан с графическим интерфейсом, и когда пользователи выходят из диалогового окна, работа потока останавливается.
Поэтому, если он запустит свою программу из примера Queued, он, вероятно, начнет писать очередь изображений, защищенных мьютексом, чтобы он мог добавлять новые изображения в список, если есть ожидающие операции сохранения. В противном случае пользователь все еще должен ждать ожидающих операций.
Вторая проблема заключается в том, что он, вероятно, не хочет ждать ожидающих операций сохранения, когда диалоговое окно закрывается.

То, что я хотел бы сделать, чтобы удовлетворить требования, работает с пулом потоков. Заполните пул потоков теми операциями сохранения, которые вы хотите, и используйте шаблон декоратора на основе QRunnable, если его также необходимо повернуть / масштабировать. Все очереди правильно обрабатываются библиотекой, и ожидающие операции выполняются, даже если пользователь покидает текущий диалог. В конце я мог бы использовать пример кода в очереди для загрузки новых изображений и дать пользователю индикацию ожидания для операции загрузки.

Мои исполняемые файлы и декоратор, вероятно, будут выглядеть следующим образом ... (возможно, некоторые дополнительные конструкторы для замены функций набора), поэтому я могу очень легко добавить новую операцию, такую ​​как QThreadPool::globalInstance()->start(saver );, без использования какого-либо низкоуровневого объекта синхронизации.

class ImageDecorator : public QRunnable
{
    NextStep nextStep;
public:
    typedef boost::shared_ptr<QRunnable> NextStep;

    ImageDecorator(const NextStep& nextStep) : nextStep(nextStep) {
    }   

    ImageDecorator() : nextStep() {
    }

    // set/get image functions....

protected:
    void next() {
        if( nextStep )
            nextStep->run();
    }
};


class RotateImage : public ImageDecorator
{
public:
    typedef boost::shared_ptr<Image> Image;

    RotateImage(const NextStep& nextStep) : ImageDecorator( nextStep) {
    }   

    RotateImage() : ImageDecorator() {
    }
    // set angle functions....

private:
    void run()
    {
        // rotate the image
        // ...
        next();
    }
};

class ResizeImage : public ImageDecorator
{
public:
    typedef boost::shared_ptr<Image> Image;

    ResizeImage(const NextStep& nextStep) : ImageDecorator( nextStep) {
    }   

    ResizeImage() : ImageDecorator() {
    }
    // set size functions....

private:
    void run()
    {
        // resize the image
        next();
    }
};

class SaveImage : public ImageDecorator
{
public:
    typedef boost::shared_ptr<Image> Image;

    SaveImage(const NextStep& nextStep) : ImageDecorator(nextStep) {
    }   

    SaveImage() : ImageDecorator() {
    }
   // set fileName functions....

private:
    void run()
    {
        // save the image
        next();
    }
};

// save the image 
SaveImage *const saver( new SaveImage() );
saver->setImage( /*use shared pointer*/ );
saver->setFilename( ... );

QThreadPool::globalInstance()->start( saver );

// rotate and save the image 
const ImageDecorator::NextStep saver( new SaveImage() );
saver->setImage( /*use shared pointer*/ );
saver->setFilename( ... );
RotateImage *const rotateAndSave( new RotateImage( saver ) );
rotateAndSave->setImage( /*use shared pointer*/ );
rotateAndSave->setAngle( ... );

QThreadPool::globalInstance()->start( rotateAndSave );


// resize rotate  and  save the image 
const ImageDecorator::NextStep saver( new SaveImage() );
saver->setImage( /*use shared pointer*/ );
saver->setFilename( ... );
const ImageDecorator::NextStep rotateAndSave( new RotateImage( saver ) );
rotateAndSave->setImage(/*use shared pointer*/ );
rotateAndSave->setAngle( ... );
ResizeImage *const resizeRotateAndSave( new ResizeImage( rotateAndSave ) );
resizeRotateAndSave->setImage( /*use shared pointer*/ );
resizeRotateAndSave->setSize( ... );

QThreadPool::globalInstance()->start( resizeRotateAndSave );
1 голос
/ 19 августа 2013

Самый простой способ сделать это - использовать QtConcurrent :: run

1 голос
/ 19 августа 2013

Либо создайте отдельный поток с QThread, либо используйте рабочие потоки пула потоков с QRunnable, либо посмотрите на класс QtConcurrent высокого уровня. Здесь - пример масштабирования изображения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...