Probleme mit QWaitCondition und QMutex

Alles rund um die Programmierung mit Qt
Antworten
MisterJ
Beiträge: 21
Registriert: 20. November 2008 12:21

Probleme mit QWaitCondition und QMutex

Beitrag von MisterJ »

Hallo,

ich habe versucht, einen Thread mit QMutex und QWaitConditon zu stoppen und dann wieder zu starten. Dabei bekomme ich aber eine access violation, wenn ich im Thread zum erstem Mal mit QMutex arbeite.

Zunächst eine Frage zu meiner Vorgehensweise:

Ist es richtig, dass ich meinem Thread einen Zeiger auf ein QMutex und ein QWaitCondition Objekt beim Erzeugen aus der aufrufenden Klasse übergebe?

Code: Alles auswählen

m_pDataThread = new DataThread(this, m_pMutex, m_pWaitCondition);
Oder muss ich in beiden Klassen eine Instanz von QMutex und QWaitCondition erzeugen?

Im Thread kommt dann bei

Code: Alles auswählen

m_pMutex->lock();
direkt eine Fehlermeldung:

Access violation reading location ...


Ich bitte um Rat, da ich anscheinend das Thema trotz Lesens der Dokumentation und einiger Seiten im Internet noch immer nicht zur Gänze zu durchblicken scheine.

Vielen Dank

Johannes
pfid
Beiträge: 535
Registriert: 22. Februar 2008 16:59

Beitrag von pfid »

Wenn du in beiden Threads ein Mutex Objekt hast, werden 2 Unterschiedliche Mutexe gesperrt, dementsprechend gar nichts geschützt/blockiert/angehalten (= ja, du musst das Mutex des anderen Threads übergeben).
WaitCond musst du keine mitgeben, die kannst du lokal im Thread (in der Methode... sonst wo) haben, so lang sie als Parameter das mitgegebene Mutex verwendet.

Viel zum Fehler kann man nicht sagen. Die Pointer die du mitgibst sind auch nicht 0, ja?
MisterJ
Beiträge: 21
Registriert: 20. November 2008 12:21

Beitrag von MisterJ »

Okay, jetzt habe ich keine Fehlermeldung mehr, aber er tut einfach nichts, wenn ich

Code: Alles auswählen

m_WaitCondition.wakeAll();
ausführe.

Im DataThread ist das so verknüpft:

Code: Alles auswählen

m_WaitCondition.wait(m_pMutex);

Johannes
RHBaum
Beiträge: 1436
Registriert: 17. Juni 2005 09:58

Beitrag von RHBaum »

Access violation reading location ...
oder der mutex wurde nicht initialisiert (unwahrscheinlich bei QMutex)
oder der mutex wurde schon deleted (oder ausm scope gelaufen) nur dein benutzender thread hat das ned mitbekommen und nutzt den (nun ungültigen) Zeiger lustig weiter ...

Ciao ...
pfid
Beiträge: 535
Registriert: 22. Februar 2008 16:59

Beitrag von pfid »

MisterJ hat geschrieben:Okay, jetzt habe ich keine Fehlermeldung mehr, aber er tut einfach nichts, wenn ich

Code: Alles auswählen

m_WaitCondition.wakeAll();
ausführe.

Im DataThread ist das so verknüpft:

Code: Alles auswählen

m_WaitCondition.wait(m_pMutex);

Johannes

Also ohne Code kann man dir wirklich nicht helfen.

Läuft dein Thread? (start() ? runloop?)
Hat der Thread vor dem waitcond.wait() das Mutex gelockt? (muss er, sonst gehts nicht)
Hat der andere Thread das Mutex gelockt?
MisterJ
Beiträge: 21
Registriert: 20. November 2008 12:21

Beitrag von MisterJ »

Okay,

hier der Code:

BasisKlasse.h

Code: Alles auswählen

QMutex * m_pMutex;
	QWaitCondition m_WaitCondition;

BasisKlasse.cpp

Code: Alles auswählen

QMutex * m_pMutex = new QMutex;
		m_pDataThread = new DataThread(this, m_pMutex);
...
m_pDataThread->start();
...
m_WaitCondition.wakeAll();

DataThread.h

Code: Alles auswählen

QMutex * m_pMutex;
	QWaitCondition m_WaitCondition;
DataThread.cpp

Code: Alles auswählen

DataThread::DataThread(QObject * parent, QMutex * pMutex)
: QThread(parent)
{
	m_pBasisKlasse = qobject_cast<BasisKlasse*>(parent);
	m_pMutex = pMutex;

...

}

void DataThread::run(void)
{
	while(...) {
		m_pMutex->lock();
		...
m_pMutex->unlock();

		m_pMutex->lock();
		...
		m_WaitCondition.wait(m_pMutex);
		m_pMutex->unlock();

...

	} // end while
}

Ich hoffe, das hilft etwas weiter.

Johannes

P.S.: Der Thread läuft bis zu dem wait aber dann nicht weiter, weil er anscheinend nicht wieder aufgeweckt wird.
pfid
Beiträge: 535
Registriert: 22. Februar 2008 16:59

Beitrag von pfid »

Okay war meinerseits unglücklich formuliert. Du musst die waitcond nicht mitgeben, um sie im thread für wait() zu benutzen. Du musst allerdings schon die waitcond mit wakeAll() aufwecken, auf der der Thread schläft. Wenn du in der basisklasse ne lokale waitcond hast, schläft auf der doch kein thread, folglich kannst du auch keinen aufwecken.

also einfach in den thread header

Code: Alles auswählen

void wakeUp() { waitCond.wakeAll(); }
und das von der basisklasse aufrufen.
MisterJ
Beiträge: 21
Registriert: 20. November 2008 12:21

Beitrag von MisterJ »

Vielen Dank, jetzt funktioniert es! :D
Antworten