01 void ImageWindow::addTransaction(Transaction *transact)

02 {

03 thread.addTransaction(transact);

04 openAction->setEnabled(false);

05 saveAction->setEnabled(false);

06 saveAsAction->setEnabled(false);

07 }

Функция addTransaction() добавляет транзакцию в очередь транзакций вторичного потока и отключает команды Open, Save и Save As на время обработки транзакций.

01 void ImageWindow::allTransactionsDone()

02 {

03 openAction->setEnabled(true);

04 saveAction->setEnabled(true);

05 saveAsAction->setEnabled(true);

06 imageLabel->setPixmap(QPixmap::fromImage(thread.image()));

07 setWindowModified(true);

08 statusBar()->showMessage(tr("Ready"), 2000);

09 }

Слот allTransactionsDone() вызывается, когда очередь транзакций TransactionThread становится пустой.

Теперь давайте рассмотрим класс TransactionThread:

01 class TransactionThread : public QThread

02 {

03 Q_OBJECT

04 public:

05 void addTransaction(Transaction *transact);

06 void setImage(const QImage ℑ);

07 QImage image();

08 signals:

09 void transactionStarted(const QString &message);

10 protected:

11 void run();

12 private:

13 QMutex mutex;

14 QImage currentImage;

15 QQueue transactions;

16 };

Класс TransactionThread содержит список обрабатываемых транзакций, которые выполняются по очереди в фоновом режиме.

01 void TransactionThread::addTransaction(Transaction *transact)

02 {

03 QMutexLocker locker(&mutex);

04 transactions.enqueue(transact);

05 if (!isRunning())

06 start();

07 }

Функция addTransaction() добавляет транзакцию в очередь транзакций и запускает поток транзакции, если он еще не выполняется. Доступ к переменной—члену transactions защищается мьютексом, потому что главный поток мог бы ее модифицировать функцией addTransaction() во время прохода по транзакциям transactions вторичного потока.

01 void TransactionThread::setImage(const QImage ℑ)

02 {

03 QMutexLocker locker(&mutex);

04 currentImage = image;

05 }

06 QImage TransactionThread::image()

07 {

08 QMutexLocker locker(&mutex);

09 return currentImage;

10 }

Функции setImage() и image() позволяют главному потоку установить изображение, для которого будут выполняться транзакции, и получить обработанное изображение после завершения всех транзакций. И вновь мы защищаем доступ к переменной—члену при помощи мьютекса.

01 void TransactionThread::run()

02 {

03 Transaction *transact;

04 forever {

05 mutex.lock();

06 if (transactions.isEmpty()) {

07 mutex.unlock();

08 break;

09 }

10 QImage oldImage = currentImage;

11 transact = transactions.dequeue();

12 mutex.unlock();

13 emit transactionStarted(transact->message());

14 QImage newImage = transact->apply(oldImage);

15 delete transact;

16 mutex.lock();

17 currentImage = newImage;

18 mutex.unlock();

19 }

20 }

Перейти на страницу:

Похожие книги