Question

I have a main thread and a thread that process some files. When there are changes in a folder monitored by the main thread, a signal is sent to the processing thread to start. After processing a file, I would like it removed and then let the folder check whether there are any more files in the folder. If there are then repeat the process.

My problem is in the repeated check of the folder. on the processing thread. The function is listed in the code below where the problem is that i cannot delete the files from the folder. I'm pretty stuck, so any inputs is appreciated.

In dataprocessor.h

...
QList<QString> justProcessed;
...

In dataprocessor.cpp

void DataProcessor::onSignal() {
// Will keep running as long as there are files in the spool folder, eating it's way through
bool stillFiles = true;

QDir dir(this->monitoredPath);
dir.setFilter(QDir::Files | QDir::NoDotAndDotDot);
dir.setSorting(QDir::Time);

while(stillFiles) {

    // Have to update on each iteration, since the folder changes.
    dir.refresh();

    QFileInfoList fileList = dir.entryInfoList();
    QString activeFile = "";

    foreach(QFileInfo file, fileList) {

        if((file.suffix() == "txt") && !justProcessed.contains(file.fileName())) {
            // Is a text file. Set for processing and break foreach loop
            activeFile = file.fileName();
            break;
        }

    }

    // If none of the files passed the requirements, then there are no more spl files in the folder.
    qDebug() << activeFile;
    if(activeFile == "") {
        qDebug() << "Finished";
        emit finished();
        stillFiles = false;
    }

    // File is a new file, start processing
    qDebug() << "Selected for processing";
    qDebug() << monitoredPath + "/" + activeFile;
    if(!dir.remove(monitoredPath + "/" + activeFile)) qDebug() << "Could not remove file";

    justProcessed.append(activeFile);

} // While end
}

Please let me know if I missed to provide some information.

Was it helpful?

Solution

The problem turned out to be two problems. One of the problems was that the system was too fast, hereby reading and deleting the files at the same time as the system. I resolved this problem by adding a QTimer which was reset each time a signal from the monitored folder was fired. 500ms from the last change of the system was sufficient. Instead of continuesly reading the files in this folder with QFileSystemWatcher and adding them to a queue, as i originally did, I created a function to mute the system watcher while processing the files in the folder. To compensate the function of the file watcher, i created a recursive loop in the processing thread so that it would keep reading the specified files for as long as there still were files. This could be done in one thread though. You all talk code, so here goes:

Signal and slot setup

// Setting up folder monitoring.
watcher.addPath(worker->monitoredPath);
QObject::connect(&watcher, SIGNAL(directoryChanged(QString)), this,
SLOT(updateQueue()));
// Timer
connect(timer, SIGNAL(timeout()), this, SLOT(startProcess()));
connect(this, SIGNAL(processRequest()), thread, SLOT(start()));
...

void MainWindow::updateQueue() {
  // Starts or restarts the call to start process. Prevents multiple signals from
  // many files added at once
  timer->start(500);
}
...
void MainWindow::startProcess() {

  if(!thread->isRunning()) {
    emit processRequest();
    muteWatcher(true);  // From here on a recursive loop in dataprocessor checks
                        // the folder for new files.
  }
  timer->stop();

}

Mute file watcher

void MainWindow::muteWatcher(bool toggle) {
  if(toggle) {
    watcher.removePath(worker->monitoredPath);
  } else {
    watcher.addPath(worker->monitoredPath);
  }
}

Processing thread

void DataProcessor::initialize() {
  QDir dir(this->monitoredPath);
  dir.setFilter(QDir::NoDotAndDotDot | QDir::Files);
  dir.setSorting(QDir::Time);

  QList<QString> dFiles;

  foreach(QFileInfo file, dir.entryInfoList()) {

    if(file.suffix().toLower() == "txt") {
        dFiles.append(file.fileName());
    }
  }

  if(dFiles.count() == 0) { // Base case
    emit muteWatcher(false); // Start monitoring the folder again
    emit finished(); // end the thread
    return true;
  }

  // PROCESSING HERE

  initializeLabel();

}

The next thing was to go to go to the preferences of the printer i was printing to, in order to prevent this printer from adding spool files to the folder. You can enable this by clicking "print directly to printer". This solved most of my problems and i was able to delete a web of delays that i had created in order to prevet the program from reading the files produced by the printer.

Hope this helps someone!

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top