0

Now I want to create a thread and put in my class "AVC_file" inatance.

But when I print currentThreadId in textBroswer, I found MainWindows's threadID is same with the thread I created. show pitures like below.

Framework::Framework(QWidget * parent) : QMainWindow(parent)
{
  ui.setupUi(this);

  int threadID = (int)QThread::currentThreadId();
  ui.textBrowser->append("Main Tread ID : " + QString::number(threadID));
}

void Framework::on_OpenAVCFile_clicked()
{
    QString filePath = QFileDialog::getOpenFileName(
        this, tr("Open File"), "C:\\", "AVC File (*.avc)"
    );


    if (!filePath.isEmpty())
    {
        QMessageBox::information(this, tr("File Name"), filePath);
    }

    QFile file(filePath);
    if (!file.open(QIODevice::ReadOnly))
    {
        QMessageBox::information(0, "info", file.errorString());
    }
    else {
        QThread *thread = new QThread(this);
        int threadID = (int)thread->currentThreadId();
        ui.textBrowser->append("Second Tread ID : " + QString::number(threadID) + "\n");
        AVC_File *AVC_file = new AVC_File();

        AVC_file->moveToThread(thread);
        connect(AVC_file, SIGNAL(requestFileContent(QString)), this, SLOT(addFileContent(QString)));
        connect(AVC_file, SIGNAL(requestFileDebug(QString)), this, SLOT(addFileDebug(QString)));
        connect(AVC_file, SIGNAL(requestFileCorrectness(bool, int)), this, SLOT(adddFileCorrectness(bool, int)));
        connect(AVC_file, SIGNAL(requestNewValue(unsigned int, int)), this, SLOT(addNewValue(unsigned int, int)));
        thread->start();

        AVC_file->AVC_FileCheck(file);
    }
}

Images about my code and results--> Main Windows, create thread and results

Oh!I also try emit info in my "AVC_file" instance?like below.

void AVC_File::AVC_FileCheck(QFile &file)
{
    int threadID = (int)QThread::currentThreadId();
    emit requestFileContent("Thread ID by emit" + QString::number(threadID) + "\n");
    QTextStream in(&file);
    ........
    ........
}

Emit threadID info

Anyone can help me?

BTW, I use visual studio Qt add-in to develop this project.

Kuba hasn't forgotten Monica
  • 95,931
  • 16
  • 151
  • 313

2 Answers2

5

QThread::currentThreadId() is a static method.

When you call it, it returns the thread ID of the thread that executes it.

In both your cases that's the main thread.

Kevin Krammer
  • 5,159
  • 2
  • 9
  • 22
2

There are several issues that I'll address in random order.

First of all, using thread IDs is bad user experience. Give the threads a descriptive name:

int main(...) {
  QApplication app(...);
  QThread myThread;
  MyObject myObject;
  myObject->moveToThread(&myThread);
  QThread::currentThread()->setObjectName("mainThread");
  myThread.setObjectName("myThread");
  ...
}

Then use QThread::currentThread()->objectName() to retrieve it. You can also pass QObject* to qDebug() to display the name of the thread:

qDebug() << QThread::currentThread();

Your signal invocation would then become:

QString currentThreadName() {
  return QThread::currentThread()->objectName().isEmpty() ?
    QStringLiteral("0x%1").arg(QThread::currentThread(), 0, 16) :
    QThread::currentThread()->objectName();
}

   ...
   emit requestFileContent(
     QStringLiteral("Emitting from thread \"%1\"\n").arg(currentThreadName));

Then, use the above to deal with the thread you've created:

    auto thread = new QThread(this);
    thread->setObjectName("fileThread");
    ui.textBrowser->append(QStringLiteral("Worker thread: \"%1\").arg(thread->objectName()));
    auto AVC_file = new AVC_File;

    AVC_file->moveToThread(thread);
    ...

But AVC_FileCheck is invoked from the main thread. Whether that's OK or not depends on how that method is implemented. It needs to be thread-safe, see this question for a discussion of that. TL;DR: The following pattern could be a starting point:

class AVC_file : public QObject {
  Q_OBJECT
  Q_SLOT void fileCheck_impl(QIODevice * dev) {
    dev->setParent(this);
    ...
  }
  Q_SIGNAL void fileCheck_signal(QIODevice *);
public:
  void fileCheck(QIODevice *dev) { fileCheck_signal(dev); }
  AVC_file(QObject *parent = nullptr) : QObject(parent) {
    connect(this, &AVC_file::fileCheck_signal, this, &AVC_file::fileCheck_impl);
    ...
  }
};

Finally, your existing AVC_fileCheck API is broken. You pass QFile by reference: this won't ever work since it ceases to exist as soon as on_OpenAVCFile_clicked returns. When AVC_file uses that file in its thread, it's a dangling object reference.

Instead, you must pass the ownership of the file to AVC_file, and pass a pointer to an instance that AVC_file will dispose when done with. Or simply let AVC_file open the file for you!

Community
  • 1
  • 1
Kuba hasn't forgotten Monica
  • 95,931
  • 16
  • 151
  • 313