dou_uod 2023-08-16 14:14 采纳率: 66.7%
浏览 17
已结题

Qt多线程Qrunnable问题,connect问题

把一个结构体指针传入一个类,构造函数中指针的值是对的,到成员函数中,debug模式跟踪的值就变成0xcd,cd、cd、cdcd、cd0000了,但在成员函数中依然能按构造函数的值访问结构体里的成员,但是用emit发射信号时,将结构体里各个值发射出去的时候,值会改变,乱码崩溃都有可能,每个emit之前都把结构体中的成员打印一遍,都是正常的。

class QThreadPool;
class QTableWidgetItem;
class QMenu;
class QAction;
class RunExe : public QObject, public QRunnable
{
    Q_OBJECT
public:
    typedef struct /*exeStruct*/{
        long long mUid = -1;   //uid
        QString mName;  //名称
        QString mPath;
        int mPriority = 0;  //优先级
        QString mStatus = "Waiting";
        QString mExePath;       //程序路径
        QString mExeParamers;   //程序参数

    }EXE;
    RunExe(EXE *, QTableWidgetItem *);
    ~RunExe();
    
    bool isRunning() const;
    void waitForFinished();
    long long getUid() const;
    void setCancel();
    
protected:
    void run();

    
signals:
    void sigExeFinished(const long long &, const QString &, const QString &, QTableWidgetItem *);
    
private:
    EXE *mParamer;
    QTableWidgetItem *pItem;
    bool isCancel;
    bool isFinished;
};

class TaskMonitor : public QWidget
{
    Q_OBJECT
    
public:
    explicit TaskMonitor(QWidget *parent = nullptr);
    ~TaskMonitor();
    
    void setProjPath(const QString &);
    void setExeInfo(const RunExe::EXE &);
    void closeSoft();   //程序关闭
    
private:
    void iniRightMenu();
    void iniInterface();
    
    void saveTask();
    void loadTask();
    
protected:
    void contextMenuEvent(QContextMenuEvent *); //显示右键菜单
    
signals:
    void sigUpdateResult(const QString &);
    void sigResultError(const QString &);
    
private slots:
    void sltAlterTaskPriority(); //修改任务优先级
    void sltExeFinished(const long long &, const QString &, const QString &, QTableWidgetItem *);
    
private:
    Ui::TaskMonitor *ui;
    static QMutex mutex;
    QString mProjectPath;   //工程路径
    QThreadPool *pCallExePool;  //线程池
    QMap<long long, RunExe *> vecRunExes;
    QVector<RunExe::EXE> vecExes;
    
    QMenu *pRightMenu;
    QAction *pAlterTaskPriority;   //修改像元尺寸
};

#endif // CALLEXE_H

上面是头文件
在主线程里调用

RunExe::EXE exe;
                        exe.mUid = mProjectInfo.mCalibrationModes[n]->mUid;
                        exe.mName = file.baseName();MLOG<<"file.baseName() = "<<file.baseName();
                        exe.mPath = mProjectInfo.mCalibrationModes[n]->mSavePath + "/" + prjFile.baseName() + CALIBRATIONSUFFIXXML;
                        exe.mExePath = QCoreApplication::applicationDirPath() + "/test/xx.exe";

                        
                        exe.mExeParamers.push_back(calibrationPath);
                        Optima::CheckerBoard *caliMode = dynamic_cast<Optima::CheckerBoard *>(mProjectInfo.mCalibrationModes[0]);
                        exe.mExeParamers.push_back("|"+QString::number(caliMode->nCheckerBoardNumOfX));
                        exe.mExeParamers.push_back("|"+QString::number(caliMode->nCheckerBoardNumOfY));
                        exe.mExeParamers.push_back("|"+QString::number(caliMode->fCheckerBoardSize));
                        exe.mExeParamers.push_back("|"+QString::number(mProjectInfo.mCamInfos[0].mUid)+QString::number(mProjectInfo.mCamInfos[0].calibNum+1)+".txt");
                        
                        pTaskMonitor->setExeInfo(exe);

进入setExeInfo函数

void TaskMonitor::setExeInfo(const RunExe::EXE &exe)
{
    QList<QTableWidgetItem *> items = ui->CallExe_Table->findItems(QString::number(exe.mUid), Qt::MatchExactly | Qt::MatchRecursive);
    if (!items.isEmpty())
    {
        if (vecRunExes.find(exe.mUid) != vecRunExes.end())
            return;

        int row = items[0]->row();
        if (ui->CallExe_Table->item(row, 3)->text() != "Completed" || ui->CallExe_Table->item(row, 3)->text() != "Error")
            return;

        if (!pCallExePool->tryTake(vecRunExes[exe.mUid]))
            return;

        vecRunExes.remove(exe.mUid);

        ui->CallExe_Table->item(row, 3)->setText("Waiting");
        for (int n = 0; n < vecExes.size(); ++n)
        {
            if (vecExes[n].mUid != exe.mUid)
                continue;

            RunExe *_run = new RunExe(&vecExes[n], ui->CallExe_Table->item(row, 3));
            connect(_run, &RunExe::sigExeFinished, this, &TaskMonitor::sltExeFinished, Qt::BlockingQueuedConnection);MLOG;
            //connect(_run, &RunExe::sigExeFinished, this, &TaskMonitor::sltExeFinished, Qt::QueuedConnection);
            _run->setAutoDelete(true);
            vecRunExes[exe.mUid] = _run;
            pCallExePool->start(_run);

            break;
        }
        saveTask();
        return;
    }
MLOG;
    int row = ui->CallExe_Table->rowCount();
    ui->CallExe_Table->setRowCount(row + 1);

    //id
    ui->CallExe_Table->setItem(row, 0, new QTableWidgetItem(QString::number(exe.mUid)));
    ui->CallExe_Table->item(row, 0)->setToolTip(QString::number(exe.mUid));
    ui->CallExe_Table->item(row, 0)->setTextAlignment(Qt::AlignCenter);
    ui->CallExe_Table->item(row, 0)->setFlags(ui->CallExe_Table->item(row, 0)->flags() ^ Qt::ItemIsEditable);

    //name
    ui->CallExe_Table->setItem(row, 1, new QTableWidgetItem(exe.mName));
    ui->CallExe_Table->item(row, 1)->setToolTip(exe.mName);
    ui->CallExe_Table->item(row, 1)->setTextAlignment(Qt::AlignCenter);
    ui->CallExe_Table->item(row, 1)->setFlags(ui->CallExe_Table->item(row, 1)->flags() ^ Qt::ItemIsEditable);

    //Priority
    ui->CallExe_Table->setItem(row, 2, new QTableWidgetItem(QString::number(exe.mPriority)));
    ui->CallExe_Table->item(row, 2)->setToolTip(QString::number(exe.mPriority));
    ui->CallExe_Table->item(row, 2)->setTextAlignment(Qt::AlignCenter);
    ui->CallExe_Table->item(row, 2)->setFlags(ui->CallExe_Table->item(row, 2)->flags() ^ Qt::ItemIsEditable);

    //status
    ui->CallExe_Table->setItem(row, 3, new QTableWidgetItem(exe.mStatus));
    ui->CallExe_Table->item(row, 3)->setToolTip("Waiting");
    ui->CallExe_Table->item(row, 3)->setTextAlignment(Qt::AlignCenter);
    ui->CallExe_Table->item(row, 3)->setFlags(ui->CallExe_Table->item(row, 3)->flags() ^ Qt::ItemIsEditable);

    vecExes.push_back(exe);
    if (exe.mStatus == "Waiting")
    {
        RunExe *_run = new RunExe(&vecExes[vecExes.size() - 1], ui->CallExe_Table->item(row, 3));
        connect(_run, &RunExe::sigExeFinished, this, &TaskMonitor::sltExeFinished, Qt::BlockingQueuedConnection);
        //connect(_run, &RunExe::sigExeFinished, this, &TaskMonitor::sltExeFinished, Qt::QueuedConnection);
        _run->setAutoDelete(true);
        vecRunExes[exe.mUid] = _run;
        pCallExePool->start(_run);
    }
    saveTask();
}

然后就进入run函数

QProcess *pPro = new QProcess;
    MLOG<< mParamer->mExeParamers.split("|");
    QStringList paraList=mParamer->mExeParamers.split("|");
    MLOG<<paraList.size();
    QString uidCalibNum=paraList.at(4);
    pPro->start(mParamer->mExePath, mParamer->mExeParamers.split("|"));
    mParamer->mStatus = "Starting";

    MLOG<<"mparamer = "<<mParamer;
    MLOG<<"mParamer->mUid = "<<mParamer->mUid;
    MLOG<<"mParamer->mPath+,+uidCalibNum = "<<mParamer->mPath+","+uidCalibNum;
    MLOG<<"mParamer->mStatus = "<<mParamer->mStatus;
    MLOG<<"pItem = "<<pItem;
    emit sigExeFinished(mParamer->mUid, mParamer->mPath+","+uidCalibNum, mParamer->mStatus, pItem);
    if (pPro->waitForStarted(-1))
    {
        mParamer->mStatus = "Running";
        MLOG<<"mParamer->mUid = "<<mParamer->mUid;
        MLOG<<"mParamer->mPath+,+uidCalibNum = "<<mParamer->mPath+","+uidCalibNum;
        MLOG<<"mParamer->mStatus = "<<mParamer->mStatus;
        MLOG<<"pItem = "<<pItem;
        emit sigExeFinished(mParamer->mUid, mParamer->mPath+","+uidCalibNum, mParamer->mStatus, pItem);
        while (!pPro->waitForFinished(10))
        {
            if (isCancel) break;
//            if(isFinishedLiang) break;
//            qDebug()<<"not finish";
        }

        if (isCancel) {
            if (pPro) {
                pPro->kill();
                pPro->waitForFinished(-1);
                delete pPro;
                pPro = nullptr;
            }
            isFinished = true;
            mParamer->mStatus = "Error";
            MLOG<<isCancel;
            MLOG<<"mParamer->mUid = "<<mParamer->mUid;
            MLOG<<"mParamer->mPath+,+uidCalibNum = "<<mParamer->mPath+","+uidCalibNum;
            MLOG<<"mParamer->mStatus = "<<mParamer->mStatus;
            MLOG<<"pItem = "<<pItem;
            emit sigExeFinished(mParamer->mUid, mParamer->mPath+","+uidCalibNum, mParamer->mStatus, pItem);
            return;
        }

        int exitCode = pPro->exitCode();
        qDebug()<<pPro->exitCode()<<" = pPro->exitCode()";
        if (exitCode == 0)
        {
            delete pPro;MLOG;
            pPro = nullptr;MLOG;
            isFinished = true;MLOG;
            //mParamer->mStatus = QString("Completed");qDebug()<<__FUNCTION__<<__LINE__;
            MLOG<<"mParamer->mUid = "<<mParamer->mUid;
            MLOG<<"mParamer->mPath++uidCalibNum = "<<mParamer->mPath+","+uidCalibNum;
            MLOG<<"mParamer->mStatus = "<<mParamer->mStatus;
            MLOG<<"pItem = "<<pItem;
            emit sigExeFinished(mParamer->mUid, mParamer->mPath+","+uidCalibNum, /*mParamer->mStatus*/QString("Completed"), pItem);MLOG;
            return;
        }
    }
    delete pPro;MLOG;
    pPro = nullptr;
    isFinished = true;
    mParamer->mStatus = "Error";
    MLOG<<"mParamer->mUid = "<<mParamer->mUid;
    MLOG<<"mParamer->mPath+,+uidCalibNum = "<<mParamer->mPath+","+uidCalibNum;
    MLOG<<"mParamer->mStatus = "<<mParamer->mStatus;
    MLOG<<"pItem = "<<pItem;
    emit sigExeFinished(mParamer->mUid, mParamer->mPath+","+uidCalibNum, mParamer->mStatus, pItem);

run函数里打印mParamer的任何数据都没问题,但是emit出去,到sltExeFinished函数里,有时候到无法访问的地址直接崩溃,有时候uid不对,有时候status是乱码。下面是sltexefinished函数

void TaskMonitor::sltExeFinished(const long long &uid, const QString &path, const QString &status, QTableWidgetItem *item)
{
    qDebug()<<__FUNCTION__<<__LINE__<<uid<<status;
//    if (vecRunExes.find(uid) != vecRunExes.end())
//        vecRunExes.remove(uid);
//    saveTask();
//    //QStringList strList=path.split(",");
//    item->setText(status);
//    if (status == "Completed")
//        emit sigUpdateResult(path);
//    else if (status == "Error")
//        emit sigResultError(path);
}

下面是debug模式跟踪到构造函数和run函数的截图

img

img

  • 写回答

5条回答 默认 最新

  • 大米粥哥哥 2023-08-16 15:10
    关注
    1. 看一下参数传递前后地址是否相同,看你的报错应该是不一样了貌似
    2. 改用值传递
      可参考链接: https://blog.csdn.net/u011555996/article/details/124436777
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(4条)

报告相同问题?

问题事件

  • 系统已结题 8月24日
  • 已采纳回答 8月16日
  • 创建了问题 8月16日

悬赏问题

  • ¥15 高通uboot 打印ubi init err 22
  • ¥20 PDF元数据中的XMP媒体管理属性
  • ¥15 R语言中lasso回归报错
  • ¥15 网站突然不能访问了,上午还好好的
  • ¥15 有没有dl可以帮弄”我去图书馆”秒选道具和积分
  • ¥15 semrush,SEO,内嵌网站,api
  • ¥15 Stata:为什么reghdfe后的因变量没有被发现识别啊
  • ¥15 振荡电路,ADS仿真
  • ¥15 关于#c语言#的问题,请各位专家解答!
  • ¥15 这个如何解决详细步骤