【问题标题】:Qt thread ID is equal to MainWindows? (moveToThread)Qt线程ID等于MainWindows? (移动到线程)
【发布时间】:2016-12-14 11:36:10
【问题描述】:

现在我想创建一个线程并放入我的类“AVC_file”。

但是当我在 textBroswer 中打印 currentThreadId 时,我发现 MainWindows 的 threadID 与我创建的线程相同。显示如下图。

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);
    }
}

关于我的代码和结果的图片--> Main Windows, create thread and results

哦!我也尝试在我的“AVC_file”实例中发出信息?如下所示。

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

谁能帮帮我?

顺便说一句,我使用 Visual Studio Qt 插件开发这个项目。

【问题讨论】:

    标签: multithreading qt


    【解决方案1】:

    QThread::currentThreadId() 是一个静态方法。

    当你调用它时,它会返回执行它的线程的线程ID。

    在这两种情况下,这都是主线程。

    【讨论】:

    • 根据您的回答,如何在主线程中获取另一个线程ID?
    • 为什么需要一个新的ID?也许在您的 AVC_File 中存储一个 ID 以进行识别。
    【解决方案2】:

    我将按随机顺序解决几个问题。

    首先,使用线程 ID 是不好的用户体验。给线程起一个描述性的名称:

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

    然后使用QThread::currentThread()->objectName() 检索它。您还可以将QObject* 传递给qDebug() 以显示线程的名称:

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

    您的信号调用将变为:

    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));
    

    然后,使用上面的方法来处理你创建的线程:

        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);
        ...
    

    但是AVC_FileCheck 是从主线程调用的。这是否可以取决于该方法的实现方式。它需要是线程安全的,请参阅this question 进行讨论。 TL;DR:以下模式可以作为起点:

    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);
        ...
      }
    };
    

    最后,您现有的AVC_fileCheck API 已损坏。你通过引用传递QFile:这永远不会起作用,因为一旦on_OpenAVCFile_clicked 返回,它就不再存在。当AVC_file 在其线程中使用该文件时,它是一个悬空对象引用。

    相反,您必须将文件的所有权传递给AVC_file,并传递一个指向实例的指针,AVC_file 将在完成后释放该实例。或者干脆让AVC_file为你打开文件!

    【讨论】:

      猜你喜欢
      • 2015-11-21
      • 1970-01-01
      • 2010-10-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多