Threadproblem mit qextserialport

Alles rund um die Programmierung mit Qt
Antworten
taraquedo
Beiträge: 36
Registriert: 1. März 2007 13:07

Threadproblem mit qextserialport

Beitrag von taraquedo »

Hallo!

Der obere Code klappt, der scheinbar identische Code unten klappt nicht. Es ist reiner Debugcode, also nicht "sauber" (File wird nicht geschlossen) und nicht optimiert (ein Zeichen Buffer). Trotzdem entsteht im oberen Beispiel eine Datei, die Zeichen für Zeichen alles aufschreibt, was auf der seriellen Schnittstelle reinkommt.

Code: Alles auswählen

// abstractCommunicationClass stammt von QThread ab!
class serialPort : public abstractCommunicationClass
{
Q_OBJECT
	
private:
   QextSerialPort* comport;

public:
   serialPort(); // <-- Initialisierung und Öffnen von comport drin!
   ~serialPort(); // <-- Schließen des comport

   void run();
   void testfn();
};

void serialPort::testfn(void)
{
   QFile file("serial_debug.txt");
   if (!file.open(QIODevice::WriteOnly | QIODevice::Text))
      return;
   QTextStream out(&file);
   out << "Starting output\n";

   forever
   {
      // Lesen von Zeichen in den Ringpuffer, wenn notwendig
      if (comport->bytesAvailable() > 0)
      {
         char c;
         comport->read(&c, 1); // TODO: Fehlerabfrage
         out << c;
         out.flush();
      }
   }
   file.close(); // Natürlich wird diese Zeile nie ausgeführt
}

// in der Main dann
serialPort* com = new serialPort();
((serialPort*)(com))->testfn(); // Typcast zur Sicherheit
// Resultat: Klappt
Nun der Code, der nicht klappt, weil der Vergleich comport->bytesAvailable() immer unwahr endet. Außerdem sehe ich im Debugger nicht, dass er den Haltepunkt jemals erneut anfährt. Bricht er denn die Ausführung von run() danach ab!?

Code: Alles auswählen

// Klasse wie oben
void serialPort::run(void)
{
   QFile file("serial.txt");
   if (!file.open(QIODevice::WriteOnly | QIODevice::Text))
      return;
   QTextStream out(&file);
   out << "Starting output\n";

   while (true)
   {
      // Prüfen, ob Thread beendet werden soll
      stoppedLock.lockForRead();
      if (stopped)
         break;
      stoppedLock.unlock();

      if (comport->bytesAvailable() > 0) // ist immer falsch -- warum!?
      {
         char c;
         comport->read(&c, 1); // TODO: Fehlerabfrage
         out << c;
         out.flush();
      }
   }
   file.close();
   stoppedLock.unlock();
}

// Aufruf durch
serialPort* com = new serialPort();
((serialPort*)(com))->start(); // Typcast zur Sicherheit
Hat jemand eine Idee, warum plötzlich keine Bytes mehr ankommen? Die Datei entsteht, aber bleibt vollkommen leer.

Grüße!
Eltharion
Beiträge: 74
Registriert: 4. Mai 2006 14:42
Wohnort: Magdeburg
Kontaktdaten:

Beitrag von Eltharion »

Kann es sein, dass dein Thread immer schon vorher beendet wird? Kommst Du überhaupt bis "comport->bytesAvailable()"? Woher kommt die Variable "stopped"? Wie wird sie initialisiert? Gib mal Debug-Meldungen aus, wenn Du z.B. ein break machst oder wenn Du in forever/while(true) eintrittst. z.B. für jede Loop ein "." oder so. Kann mir vorstellen, dass "bytesAvailable()" die ersten paar Runden noch keine Daten hat, aber die Schleife wg. einem stopped==true einfach abgebrochen wird.

E*
taraquedo
Beiträge: 36
Registriert: 1. März 2007 13:07

Beitrag von taraquedo »

hallo!

Also das ist so, dass ich anschließend auch nochmal weiter debuged habe und folgendes feststellte:
Der Thread startet vollkommen wie geplant. Kommt jedoch der erste Aufruf, der mit comport zu tun hat (vollkommen gleich, ob bytesAvailable() oder read() oder readAll(), NICHT jedoch bei einfachen Funktionen wie isOpen() etc.) dann bricht der Thread ab. Und dieses Verhalten finde ich sehr seltsam. Er bricht wirklich ab! Es wird keine weitere Anweisung im run() ausgeführt. Das dürfte laut C bzw. C++ Syntax doch gar nicht sein.

Deshalb vermutete ich ein Problem mit Visual Studio. Ich habe also alles mit MinGW übersetzt und da ist das Problem auch.
ABER: Übersetzt man den gleichen Quelltext unter Linux, dann funktioniert alles tadellos so, wie das gedacht ist.

Meint ihr ich sollte das mal an die Betreuer bei sourceforge melden? Es scheint ja doch ein Problem mit der qextserialport lib zu sein.

Grüße!
taraquedo
Beiträge: 36
Registriert: 1. März 2007 13:07

[gelöst] Threadproblem mit qextserialport

Beitrag von taraquedo »

Ich habe es gelöst!

Wenn mir das einer erklären kann, dann kann er/sie sich stolz Jedi-Qt-Meister betiteln. Also das Problem wird durch folgendes verursacht:

Code: Alles auswählen

MeineThreadKlasse::MeineThreadKlasse(void)
{
   comport = new QextSerialPort("COM4");
   comport->open(QIODevice::ReadWrite);

   // Das löst das Problem aus:
   QMessageBox::about(0, tr("Serielle Schnittstelle"), 
      tr("Die Serielle Schnittstelle ist jetzt %1").arg(comport->open()));

}
Ich darf also aus dem Konstruktor keine grafische Oberfläche ansprechen, dann dreht die Funktion run() durch. Das ist mir unverständlich aus folgenden Gründen:
  • Das ich keine GUI ansprechen kann aus einem Thread ist mir klar. Der Konstruktor läuft aber doch im Mainthread ab
  • Warum treten die Problem in Form von unerklärbarem Verhalten dann erst im run(), also im eigenen Thread auf und nicht schon da, wo der Fehler gemacht wurde. Also im Konstruktor.
Wenn mir das einer beantworten könnte oder versuchen kann, dann wäre ich um einiges im Umgang mit Threads schlauer. Aber ich vermute, das die Sache nicht so durchsichtig ist.

Grüße!
Antworten