Seite 1 von 1

Ports parallel abfragen

Verfasst: 25. Oktober 2010 15:30
von darkshine
Hallo Qt-Gemeinde,

ich habe ein Terminalprogramm geschrieben. Ich stelle den Comport und Baudrate ein und mit "V" meldet sich mein Gerät.
Nun wollte ich es automatisieren und an alle Com-Ports ein V senden und schauen welcher sich meldet.
Dies habe ich in einer Schleife gelöst:

1. Port öffnen
2. "V" senden
3. Auf eine Antwort warten
4. Port schließen
5. Nächsten Port öffnen

Das klappt auch alles. Allerdings nutze ich auch Bluetooth und da werden gerne mal 10 oder mehr Ports angelegt die abgefragt werden müssen. Da dauert es wirklich sehr lange.
Es sollte aber doch möglich sein alle Ports gleichzeitig zu öffnen und schauen welcher Port sich zurück meldet.
Ich habe es mit Objekten versucht. Dafür erstelle ich z.B 10 Comport Objekte und weise jedem Objekt einen eigenen Port zu. Leider habe ich dadurch keine Geschwindigkeitsverbesserung erziehlt.

Wären Threads eine Lösung? Ich habe allerdings von Threads gar keine Ahnung und weiß nicht, was diese überhaupt leisten können.

Vielen Dank

Verfasst: 25. Oktober 2010 17:10
von upsala
Wie werden die Daten ausgelesen? Wie sieht der Code dazu aus?

Verfasst: 26. Oktober 2010 08:03
von darkshine
Ich erstelle comport Objekte und weise den Objekten jeweils einen vorhandenen Comport zu. Die Objekte speichere ich einer einer QHash. Welche Comports wirklich existieren habe ich vorher abgefragt und in einer QStringlist comliste gespeichert.
Die comliste gibt dann einen String in der Form "COM1" usw zurück.

Code: Alles auswählen

QHash<int, Comports*> porthash;
	
for(int i=0; i<=9; i++)
{		
		porthash[i] = new Comports(comliste.at(i));
}
In der Klasse Comports findet die Abfrage statt.

Code: Alles auswählen

Comports::Comports(QString com)
{
	comport = com;	
	verbinde();
	qDebug() << "Erstelle Port";
}

Code: Alles auswählen

void Comports::verbinde()
{			


		portIni(comport); //ComPort wird inistalisiert
		
		// Sende ein V und warte schaue ob sich etwas am Port zurück meldet
		WriteFile(hCom,"V",1,&dwBytesWritten,0); 
                qWait(100); //Warte 100ms
		
		ReadFile(hCom,&output,1000,&dwBytesRead,0);	


			if(dwBytesRead != 0)
			{
				//Es gab eine Antort auf "V". Mein Gerät wurde gefunden				
			}	
			CloseHandle(hCom);
			
}	
Wenn ein Objekt erstellt wurde, dauert es doch recht lange bis das Nächste erstellt wird.
Ich würde gerne alle Objekte "gleichzeitig" erstellen und z.B nach 5Sek abfragen, ob sich auf einem Port etwas auf "V" gemeldet hat.
Ich hatte mit einen Gschwindigkeitsgewinn durch die Erstellung von Objekten in der for-Schleife erhofft, aber leider half es nichts :-(

Verfasst: 26. Oktober 2010 09:08
von upsala
Sind writeFile und readFile in diesem Falle blockierende Funktionen? Wenn ja, dann erstell dir einen Thread und frage dort ab, wenn nicht kannst du das ganze doch mit Timern pollen.

Verfasst: 26. Oktober 2010 09:22
von solarix
Ohne ein vollständiges Pflichtenheft sind Tipps zum Aufbau einer Software immer schwierig (bis sogar gefährlich..). Aber das, was du bisher gezeigt hast, könnte man schon als Thread-Anwendung implementieren.

Es gibt immer viele Möglichkeiten, eine (Thread-)Anwendung zu implementieren, aber ich zeig mal ein paar Schlüsselstellen zu einer möglichen Lösung:

Initialisierung:

Code: Alles auswählen

  QThread   *context1 = new QThread();
  Comports  *comPort = new Comports();

  // Startet den Auftrag, sobald der Thread läuft
  connect(context1,SIGNAL(started()),  
              comPort, SLOT(testPort()));

  // Liefert das Ergebnis
  connect(comPort,SIGNAL(deviceDetected(QString,bool)),  
              this, SLOT(portResult(QString,bool)));
   
  comPort->moveToThread(context1 );
  context1->start();

Methode testPort:

Code: Alles auswählen

void Comports::testPort()
{         
      portIni(comport); //ComPort wird inistalisiert
      
      // Sende ein V und warte schaue ob sich etwas am Port zurück meldet
      WriteFile(hCom,"V",1,&dwBytesWritten,0);
      qWait(100);
      
      ReadFile(hCom,&output,1000,&dwBytesRead,0);   

      if(dwBytesRead != 0)
        emit deviceDetected(comport,true);
      else 
        emit deviceDetected(comport,false);

      CloseHandle(hCom);
}  
Die Grundlagen zu den Threads musst du dir natürlich selbst erarbeiten.

hth..

Verfasst: 26. Oktober 2010 09:55
von RHBaum
Für lese und schreibe operationen auf ressourcen bietet windows eh die "assynchronen Ports" an ...
Man kann also den lesevorgang starten lassen und hinterlegt eine routine, die gefeuert wird wenn die daten vollstaendig gelesen wurden.
Das ist so ziemlich das effektivste unter windows fuer assynchrones lesen. Braucht man keine threads zu (macht das BS).

Da hier effektivitaet ned im Vordergrundsteht, kann man das threaden auch selbst uebernehmen und weiterhin blockierende aufrufe verwenden ... Ist IMHO etwas intuitiver zu programmieren. mit den Overlapped und callbacks kriegt man noch mehr Kopfschmerzen auf Dauer als wie mit threading :-) Wobei es schon miteinander verwand ist :-)

"Pollen" macht IMHO wenig Sinn bei threads + blockierenden zugriffen.
mann kann die timouts fuer read und write so stellen, das die dinger "ewig auf daten warten" ... warum dann pollen ?

Ciao ...

Verfasst: 26. Oktober 2010 11:32
von darkshine
Ich habe ein einfaches QThread-Beispiel im Internet gefunden und auf mein Program übertragen.
Es läuft jetzt so ab:

Code: Alles auswählen

void Comports::run()
{    

      qDebug() << "run() läuft";

      portIni(comport); //ComPort wird inistalisiert
      
      // Sende ein V und warte schaue ob sich etwas am Port zurück meldet
      WriteFile(hCom,"V",1,&dwBytesWritten,0);
                qWait(100); //Warte 100ms
      
      ReadFile(hCom,&output,1000,&dwBytesRead,0);   


         if(dwBytesRead != 0)
         {
            //Es gab eine Antort auf "V". Mein Gerät wurde gefunden            
         }   
         CloseHandle(hCom);
         
}    
Und im Hauptprogram

Code: Alles auswählen

      for(int i=0; i<=9; i++)
	{		
		porthash[i] = new Comports(comliste.at(i));
	}	
	
	for(int i=0; i<=9; i++)
	porthash[i]->start();
Dadurch hat sich die "Abfragegeschwindigkeit" mehr als verdoppelt.

Dies ist bestimmt nicht der Königsweg, aber schon ein großer Fortschritt für mich