GUI thread und pthread

Alles rund um die Programmierung mit Qt
Antworten
D.Cent
Beiträge: 44
Registriert: 25. Juli 2007 15:39

GUI thread und pthread

Beitrag 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?
franzf
Beiträge: 3114
Registriert: 31. Mai 2006 11:15

Re: GUI thread und pthread

Beitrag 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?
solarix
Beiträge: 1133
Registriert: 7. Juni 2007 19:25

Beitrag 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.
D.Cent
Beiträge: 44
Registriert: 25. Juli 2007 15:39

Beitrag von D.Cent »

Ok, ihr habt mich überredet. Habe jetzt QThread genommen - damit geht's.
Danke für die Antworten.
Antworten