把一个结构体指针传入一个类,构造函数中指针的值是对的,到成员函数中,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函数的截图

