QProcess program indítása programból

2011.05.23. 13:43 | arabiata | Szólj hozzá!

Címkék: ipc qprocess program indítás startdetached

Jelen feladatban több automata adatait kell összegyűjteni egy adatbázisba. Ehhez vagy külön - külön megírjuk minden automata vezérlőprogramját vagy többszálú (multithread) programozással futtatjuk a lekérdező alkalmazásokat. Multithread programozásnál figyelni kell a futó szálak prioritására. Mire gondolok? Ha vannak mondjuk soros és tcp kapcsolatot használó automaták, akkor a sorosnak kell nagyobb prioritást adni az érzékenyebb adatátvitel miatt. Ezzel lelassítjuk a többi szál futását. Elméletben igen sok szálat indíthatunk, gyakorlatilag a szinkronizálási és üzenetváltási gondok miatt nem érdemes ezt a megoldást erőltetni. Tapasztalatom szerint többszálú megoldással négy modemet tud egy program kiszolgálni.  Ráadásul, ha leáll vagy befagy a szálakat kezelő program, akkor a többinek is kakukk. Tehát jobb megírni a külön futó vezérlő programokat. Technikailag nem kell többet programozni, mindkét megoldás  - az adatfeldolgozás szempontjából - ugyanazokat az elemeket tartalmazza.

Egy programnak másikból történő indítására a QProcess osztály szolgál. Az indító utasítások:

  • start -> elindítja a programot új processként, ha még nem fut
  • execute -> elindítja a programot új processként és vár a befejezésre
  • startDetached -> elindítja a programot új processként és leválik róla (elfelejti)

 Mindhárom megoldásnál QStringList-ben tudjuk átadni az indító paramétereket 

const QString & program, const QStringList & arguments

 

formában. Nekünk a startDetached kell. A vonatkozó programrészlet:

void StartCommForm::inditas_leallitas(QTableView *nezet, QString to_do) {

 

QSqlQuery query(db_leiro), allapot(db_leiro);

query.prepare("select * from automatak where automata_id = :0");

QString automata_id;

QStringList params;

QItemSelectionModel *munka = nezet->selectionModel();

QList<QModelIndex> kivalasztottak(munka->selectedRows(3));


for (int i = 0; i < kivalasztottak.count(); i++) {

    automata_id = kivalasztottak.at(i).data().toString();

   if (to_do == "I"){

      query.bindValue(0,automata_id);

      query.exec();

      query.next();

      for (int j = 4; j < 13; j++){

        params << query.value(j).toString();

       QProcess progi;

     if (progi.startDetached(query.value(2).toString(), params) == false){ // nem indult el

     allapot.prepare("update automatak set hiba = :0, fut = 'Nem' where  automata_id = :1");

     allapot.bindValue(0, hibakodok.at(progi.error()));

     allapot.bindValue(1, automata_id);

     allapot.exec();

    }else{ // elindult

    allapot.prepare("update automatak set hiba = :0, fut = 'Igen' where  automata_id = :1");

    allapot.bindValue(0, hibakodok.at(6));

    allapot.bindValue(1, automata_id);

    allapot.exec();

  } // elindult vagy nem if vege

}

 

}else{

 allapot.prepare("update automatak set hiba = :0, fut = 'Nem' where automata_id = :1");

 allapot.bindValue(0, hibakodok.at(6));

 allapot.bindValue(1, automata_id);

 allapot.exec();

 } // inditas vagy leallitas if vege

 

} // for

 Nézzük részleteiben:

inditas_leallitas(widget.indito_tableView, "I");

Átadom az automatákat tartalmazó tableView-t, és "I"ndítás vagy "L"eállítás kell-e.

QItemSelectionModel *munka = nezet->selectionModel();

QList<QModelIndex> kivalasztottak(munka->selectedRows(3));


for (int i = 0; i < kivalasztottak.count(); i++) {

    automata_id = kivalasztottak.at(i).data().toString();

 

 A tableView-t multiselectre állítottam, így nem kell ctrl-t nyomkodni ha több elemet akarok kiválasztani. A kiválasztott sorok harmadik oszlopának tartalmát betöltöm egy QList-be, és ezt pörgetem végig. Így tudni fogom az indítandó automaták egyedi azonosítóját. Ennek alapján megtudom az összes adatot az automatákról:

select * from automatak where automata_id = :0

 A params QStringList-ben a kommunikációra vonatkozó összes paramétert betöltöm, majd az automatát vezérlő program kiválogatja a neki kellőket.

A startDetach vissztérő állapotától függően írom vissza az adatbázisba az automata futási állapotát.

QStringList hibakodok << "FailedToStart" << "Crashed" << "Timedout" << "ReadError" << "WriteError" << "UnknownError" << "Running";

Az utolsó else ágba kerül majd a leállítás, amit egy local kliens - szerver tcp kapcsolaton keresztül oldunk meg. Konkrétan az indító progi futtat majd egy szerver ágat, amire a kliensek minden adatátviteli ciklus után felkapcsolódnak. Ha megkapják a leállító üzenetet, befejezik a futást. Felmerülhet a kérdés, hogy miért ezt a megoldást választom. Mert csak ez multiplatformos, a D-Bus (ha jól tudom) linux specifikus. A Sharedmemory pedig a leírás szerint is beragad linux alatt és csak kézzel (ipcs, ipcrm) lehet kipiszkálni.

De hogy veszem át a paramétereket az indított programban? Így:

 osztaly::osztaly(QStringList params){


  QStringList adatok(params);

  qDebug() << adatok.count();


}


osztaly::~osztaly(){

}

//---------------------------------------------------------------------

int main(int argc, char *argv[]) {


QCoreApplication app(argc, argv);

osztaly x(app.arguments());


return app.exec();

 Az app.arguments() kimenete egy stringlist. Ezt átadom a futtató osztály konstruktorának, és innen már egyenes az út.

A bejegyzés trackback címe:

https://qtqt.blog.hu/api/trackback/id/tr682926001

Kommentek:

A hozzászólások a vonatkozó jogszabályok  értelmében felhasználói tartalomnak minősülnek, értük a szolgáltatás technikai  üzemeltetője semmilyen felelősséget nem vállal, azokat nem ellenőrzi. Kifogás esetén forduljon a blog szerkesztőjéhez. Részletek a  Felhasználási feltételekben és az adatvédelmi tájékoztatóban.

Nincsenek hozzászólások.
süti beállítások módosítása