Write file from another thread



  • Hi. I want to write file from another thread, beacuse i need to have possibility to stop writing process when i'm pressing some button. When i'm writing file without multithreading (i.e. using main thread), elapsed time of file writing process is about 86 seconds. But with threads elapsed time is about 176 seconds. Why is this? And how i can reduce this time? Code is below. Mainwindow is main thread, write_file is another.

    //mainwindow.h
    
    #ifndef MAINWINDOW_H
    #define MAINWINDOW_H
    
    #include <QMainWindow>
    #include <QThread>
    #include "write_file.h"
    
    namespace Ui {
    class MainWindow;
    }
    
    class MainWindow : public QMainWindow
    {
        Q_OBJECT
    
    public:
        explicit MainWindow(QWidget *parent = 0);
        bool play;
        QThread *thread;
        write_file *file;
        ~MainWindow();
    
    private slots:
        void on_start_count_button_clicked();
        void update(int);
        void update_time(int);
    
    private:
        Ui::MainWindow *ui;
    };
    
    #endif // MAINWINDOW_H
     
    //mainwindow.cpp
    
    #include "mainwindow.h"
    #include "ui_mainwindow.h"
    
    MainWindow::MainWindow(QWidget *parent) :
        QMainWindow(parent),
        ui(new Ui::MainWindow)
    {
        ui->setupUi(this);
    
        thread = new QThread;
        file = new write_file;
    
        file->moveToThread(thread);
    
        connect(file, SIGNAL(send_count(int)), this, SLOT(update(int)));
        connect(file, SIGNAL(send_time(int)), this, SLOT(update_time(int)));
        connect(thread, SIGNAL(started()), file, SLOT(count()));
        connect(thread, SIGNAL(finished()), thread, SLOT(terminate()));
    
        play = false;
        mFile.setFileName("D:/Qt_repo/build-model_file-Desktop_Qt_5_7_0_MSVC2013_64bit-Release/file.bin");
    }
    
    MainWindow::~MainWindow()
    {
        delete ui;
    }
    
    void MainWindow::on_start_count_button_clicked()
    {
        play = !play;
        if(play) {
            ui->start_count_button->setText("Стоп");
            thread->start();
        }
        else
        {
            ui->start_count_button->setText("Старт");
            file->stop = true;
            thread->quit();
        }
    }
    
    void MainWindow::update(int new_val)
    {
        ui->progressBar->setValue(new_val);
    }
    
    void MainWindow::update_time(int new_time)
    {
        double t_sec = ((double)new_time)/1000.0;
        ui->time_label->setText(QString::number(t_sec));
    }
     
    //write_file.h
    
    #ifndef WRITE_FILE_H
    #define WRITE_FILE_H
    
    #define BUF_SIZE 16384
    
    #include <QObject>
    #include <random>
    #include <QTime>
    #include <QFile>
    #include <QDataStream>
    
    #include <QtDebug>
    
    class write_file : public QObject
    {
    Q_OBJECT
    public:
        write_file();
        bool stop;
        QFile mFile;
        short data[BUF_SIZE];
        std::mt19937 mt_gen;
        int i;
        int el_time;
        QTime myTimer;
    signals:
        void send_count(int);
        void send_time(int);
    public slots:
        void count();
    };
    
    #endif // WRITE_FILE_H
    
    //write_file.cpp
     
    #include "write_file.h"
    #include "Windows.h"
    
    write_file::write_file()
    {
        stop = true;
        mFile.setFileName("D:/Qt_repo/build-model_file-Desktop_Qt_5_7_0_MSVC2013_64bit-Release/file.bin");
    }
    
    void write_file::count()
    {
        myTimer.start();
    
        mFile.open(QFile::WriteOnly | QFile::Truncate);
        QDataStream stream( &mFile );
        std::poisson_distribution<int> distribution(10);
        stop = false;
        for(i = 0; i < 1e8; i++)
        {
            emit send_count(int(((double)i)/(1e8-1)*100));
            data[i%BUF_SIZE] = distribution(mt_gen);
            if((i%BUF_SIZE) == (BUF_SIZE-1)) stream.writeBytes((char *)data,BUF_SIZE*2);
            if(stop) break;
        }
        stream.writeBytes((char *)data,BUF_SIZE*2);
    
        mFile.close();
    
        el_time = myTimer.elapsed();
        emit send_time(el_time);
    }
    
    

  • Lifetime Qt Champion

    Hi and welcome to devnet,

    Adding one or more thread in an application doesn't necessarily means that your are going to get as much gain as you have higher number of threads.

    It all depends on what you are currently doing in the execution part of the thread..



  • Thank you for reply, i found a problem. Updating progress bar in main window from writing file thread decreasing the speed. When i'm taking away send_count signal and update slot from my programm, everything gets OK. But why is it happening?


  • Moderators

    @KNT5 said in Write file from another thread:

    Thank you for reply, i found a problem. Updating progress bar in main window from writing file thread decreasing the speed. When i'm taking away send_count signal and update slot from my programm, everything gets OK. But why is it happening?

    Because you are calling send_count() way too much. You are calling it for every iteration of that for loop. That is equivalent of just doing a for (;;); which will take 100% of your cpu to do nothing.

    You are also doing math, specifically division on a double. Then multiplying without bit shifts. These are expensive operations. Not something noticed on small usage but in a tight loop like that it will torture your cpu.

    Try adding:

    for (i = 0; i < 1e8; i++)
    {
       if (!(i % 1000))
          emit send_count(...);
       // the rest of your stuff   
    }
    

    And finally, you update the GUI on every call of send_count. Think about setting a delay to where it only updates that progress bar at most once every 500ms or 1s even. People don't need progress faster than that and you will save a ton of CPU time for stuff that actually matters.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.