Seite 1 von 1

GUI thread und pthread

Verfasst: 20. Juli 2009 17:11
von D.Cent
In meinem Programm nutze ich ein TableWidget als Trackertabelle für ein Spiel. Während dieser sich auf Knopfdruck aktualisiert (ca. 15 Sekunden), soll die GUI aber nicht stoppen, sondern den Tracker so lange verstecken, bis er fertig ist. Dabei soll die GUI weiterhin reagieren können.

Das ist ein Auszug der Klassendeklaration:

Code: Alles auswählen

class qd321go : public QMainWindow
{
        Q_OBJECT
        ...
        public:
                ...
                pthread_t tracker_thread;
                ServerTracker tracker; // tracker (eigene Klasse)
        public slots:
                void start_refresh();
                void show_tracker();
                ...
        signals:
                void tracker_refreshed();
};
Wenn der Tracker per Button aktualisiert wird, wird folgende Funktion aufgerufen:

Code: Alles auswählen

void qd321go::start_refresh()
{
	if ( pthread_create(&tracker_thread, NULL, ServerTracker::thread_start, this) != 0 )
	{
		msg_box("Error", "Thread error!"); // msg_box ist ein define
		return;
	}
	
	tracker.hide(); // tracker wird versteckt
	pb_refresh.setEnabled(false); // Aktualisierungsknopf disablen
}
Der Thread, der gestartet wird, führt also folgende Funktion aus:

Code: Alles auswählen

void* ServerTracker::thread_start(void* p)
{
	((qd321go*)p)->tracker.refresh();
	emit ((qd321go*)p)->show_tracker();
}
Dabei wird in der ersten Zeile die Kommunkation zwischen den Servern geregelt. Allerdings in der zweiten Zeile (mit dem "emit"), die nur ein Signal auslöst, das den Tracker wieder mit der Funktion "show()" zeigen soll, meckert Qt während der Laufzeit rum, dass ich nicht mit dem GUI-Thread arbeiten würde. Sobald ich das emit rausnehme, kommen keine Warnungen.

Ich habe extra den pthread und das Signal erstellt, damit ich genau solche Warnungen vermeiden kann.

Das Signal wurde in qd321go::setupUi() folgendermaßen connected:

Code: Alles auswählen

QObject::connect(this, SIGNAL(tracker_refreshed()), this, SLOT(show_tracker())); // show_tracker() ruft tracker.show() auf
Was habe ich falsch gemacht?

Re: GUI thread und pthread

Verfasst: 20. Juli 2009 17:24
von franzf

Code: Alles auswählen

void* ServerTracker::thread_start(void* p)
{
	((qd321go*)p)->tracker.refresh();
	emit ((qd321go*)p)->show_tracker();
}
[...]

Code: Alles auswählen

QObject::connect(this, SIGNAL(tracker_refreshed()), this, SLOT(show_tracker())); // show_tracker() ruft tracker.show() auf
Das widerspricht sich doch?!?
show_tracker ist ein SLOT, du versuchst ihn in thread_start aber zu emitten...
Und AFAIK muss für das emitten eines Signals einer fremden Klasse (ich nehme an ServerTracker !~ qd321go) ServerTracker friend von gd321go sein, SIGNALS werden private gehandhabt).

Außerdem verwirfst du mit der Verwendung von pthread Plattformunabhängigkeit! Warum verwendest du nicht QThread?

Verfasst: 20. Juli 2009 17:37
von solarix

Code: Alles auswählen

 ((qd321go*)p)->tracker.refresh();
   emit ((qd321go*)p)->show_tracker(); 
komplettes Gebastel was nichts mit OOP gemeinsam hat. Ausserdem:
* wie franzf schon sagte: nimm QThread
* Signals sind protected und koennen nicht von extern geworfen werden (man rufe statt dessen eine public-Methode des Objekts auf)
* im Thread-Kontext keine GUI-Operationen! Falls du die Daten im Thread updaten moechtest, verwende Model/View-Konzept (Model mit Thread).
* Sobald Signals/Slots im Thread verwendet werden soll, wird im Thread ein Eventloop benoetigt.

Verfasst: 20. Juli 2009 18:24
von D.Cent
Ok, ihr habt mich überredet. Habe jetzt QThread genommen - damit geht's.
Danke für die Antworten.