2016-12-14 71 views
0

现在我想创建一个线程,并把我的类“AVC_file”inatance。Qt线程ID等于MainWindows? (moveToThread)

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

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插件开发此项目。

回答

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为你打开文件!

5

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

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

在你的情况下,这是主线程。

+0

根据你的回答,我如何在主线程中获得另一个线程ID? – WilliamChen

+0

为什么你需要一个新的ID?也许在你的AVC_File中存储一个ID用于识别。 –