Qt线程ID等于MainWindows? (moveToThread)

时间:2016-12-14 11:36:11

标签: multithreading qt

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

但是当我在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

任何人都可以帮助我?

BTW,我使用visual studio Qt插件来开发这个项目。

2 个答案:

答案 0 :(得分:5)

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

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

在你的两个案例中都是主线程。

答案 1 :(得分: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为您打开文件!