Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Exchange data between threads... typical question :D
Forum Updated to NodeBB v4.3 + New Features

Exchange data between threads... typical question :D

Scheduled Pinned Locked Moved General and Desktop
16 Posts 3 Posters 15.9k Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • T Offline
    T Offline
    TheDestroyer
    wrote on last edited by
    #3

    Thank you so much! I'll try what you told me and tell you how it went :-)

    Would you know if I post anything here?

    1 Reply Last reply
    0
    • F Offline
      F Offline
      Franzk
      wrote on last edited by
      #4

      [quote author="TheDestroyer" date="1306358791"]Would you know if I post anything here?[/quote]Yes.

      "Horse sense is the thing a horse has which keeps it from betting on people." -- W.C. Fields

      http://www.catb.org/~esr/faqs/smart-questions.html

      1 Reply Last reply
      0
      • A Offline
        A Offline
        andre
        wrote on last edited by
        #5

        If you're going to use threads and signals & slots (or just QObjects, for that matter), don't forget to study "this":http://developer.qt.nokia.com/wiki/ThreadsEventsQObjects wiki entry first. Also, spend time thinking how you might be able to limit the communication between threads to an absolute minimum. Threads are most effective if they can run independently. If you need lots of locking, you're not on the right track.

        1 Reply Last reply
        0
        • T Offline
          T Offline
          TheDestroyer
          wrote on last edited by
          #6

          Thank you. I'll read it right now :)

          1 Reply Last reply
          0
          • T Offline
            T Offline
            TheDestroyer
            wrote on last edited by
            #7

            It seems to be OK to emit an object from inside the thread out to the main thread. But how can I send data from the main thread to the thread? I tried copying a meta-object to the thread but didn't work!!

            1 Reply Last reply
            0
            • F Offline
              F Offline
              Franzk
              wrote on last edited by
              #8

              Please show the code that didn't work. Also, what exactly do you mean by meta-object? In Qt a meta object is a descriptive auto-generated class that says something about a QObject. Do you possibly mean meta type?

              "Horse sense is the thing a horse has which keeps it from betting on people." -- W.C. Fields

              http://www.catb.org/~esr/faqs/smart-questions.html

              1 Reply Last reply
              0
              • T Offline
                T Offline
                TheDestroyer
                wrote on last edited by
                #9

                ah! yes I mean metatype!! :$

                I'll put most of the code here, because I'm a beginner with this, and I'm going crazy not knowing how to fix this correctly! The program has worked! but I still have some problems.

                The program is simply for downsampling. So it lowers the filesize within some ratio.
                The problem now is, if the file size is huge, the program freezes!
                and the other problem is, I want to signal the object "data" by reference! is this possible?

                here's the most of the code:

                Thread code:
                @
                void downSamplingThread::run()
                {
                passedData data;
                data = dataPassed;
                downSample(data.inputFile,data.outputFile,data.dataUnitSize,data.downSamplingRate, data);

                }
                qint16 downSamplingThread::downSample(QString inputFile, QString outputFile, quint64 dataUnitSize, quint64 downSamplingRate, passedData &data)
                {
                double progressValue = 0;
                int progressLimit = 0;
                qint64 fileSize;
                std::fstream fileReader(inputFile.toStdString().c_str(),std::ios::in | std::ios::binary);
                QFile file(inputFile.toStdString().c_str());
                if(!fileReader.is_open())
                {
                return 1;
                }
                if(inputFile == outputFile && inputFile.length() != 0)
                {
                return 3;
                }
                std::fstream fileWriter(outputFile.toStdString().c_str(),std::ios::out | std::ios::binary);
                if(!fileWriter.good())
                {
                return 2;
                }
                quint64 dataUnit = dataUnitSize;
                quint64 downsamplingRate = downSamplingRate;
                char* buffer = new char[dataUnitdownSamplingRate];
                fileSize = file.size();
                file.close();
                while(!fileReader.eof())
                {
                fileReader.read(buffer,dataUnit
                downsamplingRate);
                if(!fileReader.eof())
                fileWriter.write(buffer,dataUnit);
                progressValue = (double)(100*fileReader.tellg())/fileSize;
                if(progressLimit < floor(progressValue))
                {
                progressLimit++;
                data.progress = progressLimit;
                emit progressTimeout(data);
                }
                }
                data.enableButton = 1;
                data.progress = 100;
                emit progressTimeout(data);
                return 0;
                }
                @
                in dialog for sending the command:

                @
                ...
                connect(startButton,SIGNAL(clicked()),this,SLOT(downSampleCommand()));
                connect(thread,SIGNAL(progressTimeout(passedData)),this,SLOT(updateProgress(passedData)));
                ...
                void Dialog::downSampleCommand()
                {
                statusLabel->setText("Process started...");
                startButton->setEnabled(0);
                data.dataUnitSize = dataUnitSizeSpinbox->value();
                data.inputFile = inputPathLineEdit->text();
                data.outputFile = outputPathLineEdit->text();
                data.downSamplingRate = downSamplingRateSpinbox->value();
                data.enableButton = 0;
                thread->dataPassed = this->data; //copy
                thread->start();
                qint16 outputReturn = 0;
                //qint16 outputReturn = thread->downSample(inputPathLineEdit->text(),outputPathLineEdit->text(),dataUnitSizeSpinbox->value(),downSamplingRateSpinbox->value(),data);
                if(outputReturn == 1)
                {
                statusLabel->setText("Error reading file!");
                }
                else if(outputReturn == 2)
                {
                statusLabel->setText("Error writing file!");
                }
                else if(outputReturn == 3)
                {
                statusLabel->setText("Input and output files are the same. Error!");
                }
                else if(outputReturn == 0)
                {
                statusLabel->setText("Done!");
                }
                }
                void Dialog::setLastFilePath(QString path)
                {
                *lastFile = path;
                inputFileDialog->setDirectory(path);
                outputFileDialog->setDirectory(path);
                }
                void Dialog::updateProgress(passedData data)
                {
                progressBar->setValue(data.progress);
                startButton->setEnabled(data.enableButton);
                //QMessageBox *msg = new QMessageBox;
                //msg->setText(QVariant(data.inputFile).toString());
                //msg->show();
                }
                @

                metatype:

                @

                #include <QColor>
                #include <QDebug>
                #include <QMetaType>
                #include <QRect>

                class passedData
                {
                public:
                passedData();
                ~passedData();
                passedData(const passedData &src);
                passedData& operator=(const passedData &src);

                public:
                QString inputFile;
                QString outputFile;
                quint64 dataUnitSize;
                quint64 downSamplingRate;
                bool enableButton;
                int progress;
                signals:
                };

                Q_DECLARE_METATYPE(passedData);

                #endif // PASSEDDATA_H


                #include "passeddata.h"

                passedData::passedData()
                {
                }
                passedData::~passedData()
                {

                }
                passedData::passedData(const passedData &src)
                {
                this->dataUnitSize = src.dataUnitSize;
                this->downSamplingRate = src.downSamplingRate;
                this->enableButton = src.enableButton;
                this->inputFile = src.inputFile;
                this->outputFile = src.outputFile;
                this->progress = src.progress;
                }
                passedData& passedData::operator =(const passedData &src)
                {
                this->dataUnitSize = src.dataUnitSize;
                this->downSamplingRate = src.downSamplingRate;
                this->enableButton = src.enableButton;
                this->inputFile = src.inputFile;
                this->outputFile = src.outputFile;
                this->progress = src.progress;
                return *this;
                }
                @

                and in main, I called

                @
                qRegisterMetaType<passedData>();
                @

                The program's idea is very simple. It just reads a chunk of the file, and writes a part of the chunk again. It didn't work on a file with size 30 GB (which is a typical size we need).

                Please tell me how to make this program as effective as possible. I know I'm being dependent somehow, but I have been reading about this for long time, and I'm not getting the idea!!! :(

                Thank you for any efforts :-)

                1 Reply Last reply
                0
                • F Offline
                  F Offline
                  Franzk
                  wrote on last edited by
                  #10

                  Hm, from reading this, I wonder why exactly you want to pass the data between threads? If the program will only be down sampling, your worker should be doing the down sampling and report some progress. The setup I'd then use is practically the same, but I would only be releasing the progress counter into the world, maybe a status string if it was really important.

                  "Horse sense is the thing a horse has which keeps it from betting on people." -- W.C. Fields

                  http://www.catb.org/~esr/faqs/smart-questions.html

                  1 Reply Last reply
                  0
                  • A Offline
                    A Offline
                    andre
                    wrote on last edited by
                    #11

                    Indeed, I agree with Franzk. Quoting myself:
                    [quote]Also, spend time thinking how you might be able to limit the communication between threads to an absolute minimum. Threads are most effective if they can run independently. If you need lots of locking, you’re not on the right track.[/quote]

                    In this case, indeed, this would probably be only sending some progress information (and not too frequently either!)

                    1 Reply Last reply
                    0
                    • T Offline
                      T Offline
                      TheDestroyer
                      wrote on last edited by
                      #12

                      Thanks for the answers guys :)... another problem is present after saving the first one :D

                      This program is just a sample. I'm learning, and practicing!! and actually I find it the same if I send progress or the whole data object for a very simple reason! I'm sending a reference (in the new implementation), not an object!!! I just learned how to do it!! so it's just a pointer! (and it was my purpose from the very beginning). Is it possible or legal to emit a simple variable like long int without it being a metatype rather than emitting a whole object?

                      The only reason I didn't send the progress value alone (which I do only 100 times during the process) is because I don't want to create another metatype class that contains the progress... so adding the progress to "data" was the fastest way. Don't you agree guys?

                      Actually, guys, I'm facing another problem! I'm unable to control the thread in means of starting it and closing it. For example, if the user inputs a wrong path, or does anything wrong, I want the thread to close and another one to start from the next "start" button clicked. I tried resolving this many ways. But the only way was creating a new thread on every "Start" button clicked, which implies ignoring the previous thread instantiations... because waiting, terminating, exiting or quitting it isn't working at all!!! so on every "Start" button clicked, a call "new downSamplingThread" is done, and new connections are done. But this wastes memory! how can I avoid this? how can I make sure the threads are to be deleted?

                      @
                      void Dialog::downSampleCommand()
                      {
                      thread = new downSamplingThread(this);
                      connect(thread,SIGNAL(progressTimeout(passedData)),this,SLOT(updateProgress(passedData)));
                      connect(thread,SIGNAL(sendOutputReturn(qint16)),this,SLOT(getReturnValue(qint16)));

                      statusLabel->setText("Process started...");
                      startButton->setEnabled(0);
                      data.dataUnitSize = dataUnitSizeSpinbox->value();
                      data.inputFile = inputPathLineEdit->text();
                      data.outputFile = outputPathLineEdit->text();
                      data.downSamplingRate = downSamplingRateSpinbox->value();
                      data.enableButton = 0;
                      thread->dataPassed = this->data; //copy
                      thread->start();
                      

                      }
                      void Dialog::updateProgress(const passedData &data)
                      {
                      progressBar->setValue(data.progress);
                      startButton->setEnabled(data.enableButton);
                      //QMessageBox *msg = new QMessageBox;
                      //msg->setText(QVariant(data.inputFile).toString());
                      //msg->show();
                      }
                      void Dialog::getReturnValue(qint16 outputReturn)
                      {
                      if(outputReturn == 1)
                      {
                      statusLabel->setText("Error reading file!");
                      }
                      else if(outputReturn == 2)
                      {
                      statusLabel->setText("Error writing file!");
                      }
                      else if(outputReturn == 3)
                      {
                      statusLabel->setText("Input and output files are the same. Error!");
                      }
                      else if(outputReturn == 0)
                      {
                      statusLabel->setText("Done!");
                      }
                      thread->terminate();
                      thread->quit();
                      thread->exit(1);
                      //thread->wait();
                      //delete thread;
                      startButton->setEnabled(1);
                      }


                      void downSamplingThread::run()
                      {
                      passedData data;
                      data = dataPassed;
                      downSample(data.inputFile,data.outputFile,data.dataUnitSize,data.downSamplingRate, data);

                      }
                      qint16 downSamplingThread::downSample(QString inputFile, QString outputFile, quint64 dataUnitSize, quint64 downSamplingRate, passedData &data)
                      {
                      double progressValue = 0;
                      int progressLimit = 0;
                      quint64 fileSize;
                      QFile fileReader(inputFile);
                      fileReader.open(QFile::ReadOnly);
                      if(fileReader.error())
                      {
                      emit sendOutputReturn(1);
                      //this->quit();
                      //this->terminate();
                      //this->exit();
                      return 1;
                      }
                      QFile fileWriter(outputFile);
                      fileWriter.open(QFile::WriteOnly);
                      if(inputFile == outputFile && inputFile.length() != 0)
                      {
                      emit sendOutputReturn(3);
                      //this->quit();
                      //this->terminate();
                      //this->exit();
                      return 3;
                      }
                      if(fileWriter.error())
                      {
                      emit sendOutputReturn(2);
                      //this->quit();
                      //this->terminate();
                      //this->exit();
                      return 2;
                      }
                      quint64 dataUnit = dataUnitSize;
                      quint64 downsamplingRate = downSamplingRate;
                      char* buffer = new char[dataUnitdownSamplingRate];
                      fileSize = fileReader.size();
                      quint64 i = 0;
                      while(i < fileSize)
                      {
                      fileReader.read(buffer,dataUnit
                      downsamplingRate);
                      fileWriter.write(buffer,dataUnit);
                      progressValue = (double)(100*fileReader.pos())/fileSize;
                      if(progressLimit < floor(progressValue))
                      {
                      progressLimit++;
                      data.progress = progressLimit;
                      emit progressTimeout(data);
                      }
                      i += dataUnit * downsamplingRate;
                      }
                      data.enableButton = 1;
                      data.progress = 100;
                      emit progressTimeout(data);
                      sendOutputReturn(0);
                      return 0;
                      }

                      @

                      so how can I stop this thread after failing to open the file or in general emit an error in a way that saves memory and doesn't block the main window. Cuz if I do anything like delete thread; or thread->wait()... the window freezes for some long time!!!!!

                      1 Reply Last reply
                      0
                      • T Offline
                        T Offline
                        TheDestroyer
                        wrote on last edited by
                        #13

                        Btw, I used QFile in the new implementation because fstream was, for some reason, unable to read long files. Apparently "long int"'s precission is not enough to catch 30 gb... is this problem common? any idea? I'm using in the new implementation quint64, which works! Anything you think I should know about this?

                        1 Reply Last reply
                        0
                        • T Offline
                          T Offline
                          TheDestroyer
                          wrote on last edited by
                          #14

                          come on guys!!! It's the last part of the problem :(

                          1 Reply Last reply
                          0
                          • A Offline
                            A Offline
                            andre
                            wrote on last edited by
                            #15

                            Please allow people some time, especially in the weekend, to chew through the code you dumped on us.

                            1 Reply Last reply
                            1
                            • T Offline
                              T Offline
                              TheDestroyer
                              wrote on last edited by
                              #16

                              Sure, buddy :-)

                              1 Reply Last reply
                              0

                              • Login

                              • Login or register to search.
                              • First post
                                Last post
                              0
                              • Categories
                              • Recent
                              • Tags
                              • Popular
                              • Users
                              • Groups
                              • Search
                              • Get Qt Extensions
                              • Unsolved