Qt啟動子程式,子程式關閉時通知主程式,實現主程式對子程式的管理

一字千金發表於2020-08-27

自己開發了一個股票智慧分析軟體,功能很強大,需要的點選下面的連結獲取:

https://www.cnblogs.com/bclshuai/p/11380657.html

1.需求描述 

Qt主程式啟動之後,在啟動一個程式的四個子程式,子程式關閉時,會通過狀態改變訊號,通知主程式的槽函式,實現刪除子程式的管理QProcess* 變數;

2.Qt程式QProcess介紹

2.1程式啟動方式

有兩種啟動方式,start是父子程式關聯啟動子程式。startDetached則是以分離的方式啟動程式。

   void start(const QString &program, const QStringList &arguments, OpenMode mode = ReadWrite);

    void start(const QString &command, OpenMode mode = ReadWrite);

    void start(OpenMode mode = ReadWrite);

 

 static bool startDetached(const QString &program, const QStringList &arguments,    const QString &workingDirectory

    static bool startDetached(const QString &program, const QStringList &arguments); // ### Qt6: merge overloads

    static bool startDetached(const QString &command);

 

3.實現步驟

(1)建立QMap儲存程式的QProcess* 變數;

QMap<int,QProcess*> m_processMap;

(2)主程式中獲取子程式路徑,通過for迴圈啟動四個子程式,並傳入命令列引數,同時將for迴圈的ii值作為map的key值,用於標記是哪個程式。繫結stateChanged訊號槽,之前打算用finish訊號,但是finish訊號有個過載函式,所以使用connect連線時,&QProcess::finished,無法判斷是哪個函式,所以不行。如果用SIGNAL(finish(int exitCode)),又無法用SLOT去定義lamlar表示式。為了實現i序號作為程式的標識id,程式狀態改變時,觸發訊號,可以定位到是哪個程式結束了,直接在map中刪除該程式變數。就可以了方便實現主程式和子程式之間的管理

void finished(int exitCode); // ### Qt 6: merge the two signals with a default value

    void finished(int exitCode, QProcess::ExitStatus exitStatus)

 

QString strProcessPath = QDir::currentPath() + "/AlgAnalyizeTool/AlgAnalyizeTool.exe";//AlgAnalyizeTool.exe
    if (!QFile(strProcessPath).exists())
    {
        QMessageBox::information(NULL, "提示", "分析程式不存在", QMessageBox::Yes, QMessageBox::Yes);
        return;
    }
    for (int i = 0; i < 4; i++)
    {
        QJsonObject jsonMain;
        QJsonObject serverConf;
        QJsonObject videoAnalyizeConf;
        videoAnalyizeConf.insert("cpuCores", 4);
        videoAnalyizeConf.insert("gpuNo", i);
        videoAnalyizeConf.insert("threadCount", 4);
        serverConf.insert("ip", "10.25.106.103");
        serverConf.insert("port", 8011);
        serverConf.insert("sessionId", QString::number(i));
        jsonMain.insert("serverConf", serverConf);
        jsonMain.insert("videoAnalyizeConf", videoAnalyizeConf);
        QJsonDocument root_Doc;
        root_Doc.setObject(jsonMain);
        QByteArray root_str = root_Doc.toJson(QJsonDocument::Compact);  //緊湊格式                                                            //    QByteArray root_str = root_Doc.toJson(QJsonDocument::Indented);   //標準JSON格式    QString strJson(root_str);
        
        QString strJson((root_str.toBase64()));
        QStringList Qstringlist;
        Qstringlist << strJson;
        QProcess* process=new QProcess(this);
        connect(process,&QProcess::stateChanged, this, [=](QProcess::ProcessState state) {
            if (state== QProcess::ProcessState::NotRunning)
            {
                QMap<int, QProcess*>::iterator it = m_processMap.find(i);
                if (it != m_processMap.end())
                {
                    delete it.value();
                    m_processMap.erase(it);
                }
            }
        });
        LOG_TRACE("start  begin! ");
        process->start(strProcessPath, Qstringlist);
        m_processMap[i] = process;
        LOG_TRACE("start  end! ");
    }

 

4.注意事項

4.1.主程式退出前先關閉子程式並釋放資源

以start方式啟動的子程式,需要在主程式關閉的解構函式中關閉主程式,並且刪除new出的程式指標變數;才可以正常退出。否則,資源管理器中會保留主程式和子程式。導致程式無法覆蓋或編譯生成報錯。

QMap<int, QProcess*>::iterator it = m_processMap.begin();
    for (;it!=m_processMap.end();it++)
    {
        it.value()->terminate();
        delete it.value();
    }
    m_processMap.clear();

 

相關文章