gleichzeitige QTimer-Events

Alles rund um die Programmierung mit Qt
Antworten
Cartman
Beiträge: 55
Registriert: 31. März 2006 16:55

gleichzeitige QTimer-Events

Beitrag von Cartman »

Ich benutze Qt-Commerical mit MSVC2005. Was passiert, wenn zwei QTimer-Event gleichzeitig triggern? Laufen die Events sequentiell oder parallel ab?

Code: Alles auswählen

void MainWindow::timerEvent(QTimerEvent* event)
{
   std::cout << "begin" << std::endl << std::flush;
   doSomething();
   std::cout << "end" << std::endl << std::flush;
}
Ausgabe (gelegentlich):

Code: Alles auswählen

begin
begin
end
end
QThread::currentThread() gibt allerdings immer den gleichen Wert aus. Ich benötige trotz gleichzeitiger Event-Triggerung einen sequentiellen Ablauf. Kennt sich jemand mit meinem Problem aus?

Danke.
Sephral
Beiträge: 201
Registriert: 1. Februar 2006 09:40
Kontaktdaten:

Beitrag von Sephral »

So lange Du Dich in einem Thread bewegst (GUI Thread in Deinem Fall), kann nur sequenziell abgearbeitet werden. Ich könnte mir höchstens vorstellen, dass die Ausgabe irgendwie verzögert und es daher zu einer "umsortierung" der Strings kommt.

Du könntest mal versuchen in die Ausgabe einen Zeitstempel mit Millisekunden einzufügen. Dann kann man vielleicht etwas mehr sehen.
Cartman
Beiträge: 55
Registriert: 31. März 2006 16:55

Beitrag von Cartman »

Wenn so eine Verschachtelung der Ausgabe kommt, dann sind die Zeiten auch im Msec-Bereich gleich.

Code: Alles auswählen

begin 11:51:05:654
begin 11:51:05:654
end
end
Bei dem (gelegentlich mal vorkommenden) anderen Fall sind die Zeiten verschieden:

Code: Alles auswählen

begin 11:51:08:169
end
begin 11:51:08:185
end
Ich werde jetzt mal ein hartes Geschütz auffahren: QMutex. Wenn's sequentiell ist, dann sollte der QMutex nicht deadlocken...

EDIT:

Ich habe nun ein QMutex::lock am Anfang der Event-Funktion eingefügt, ein QMutex::unlock ans Ende eingefügt. Bei gleichzeitiger Triggerung: Deadlock! Bei 1 msec Unterschied zwischen den Triggerungen: OK!

:?:
Zuletzt geändert von Cartman am 21. Juli 2008 12:53, insgesamt 1-mal geändert.
Christian81
Beiträge: 7319
Registriert: 26. August 2004 14:11
Wohnort: Bremen
Kontaktdaten:

Beitrag von Christian81 »

Wenn doSomething() qApp->processEvents() aufruft (oder auch nur irgendwie indirekt die Events abgearbeitet werden) dann kann das natürlich passieren.
Ich würde den Timer während der Abarbeitung stoppen.
MfG Christian

'Funktioniert nicht' ist keine Fehlerbeschreibung
RHBaum
Beiträge: 1436
Registriert: 17. Juni 2005 09:58

Beitrag von RHBaum »

QThread::currentThread() gibt allerdings immer den gleichen Wert aus
Dann laufen die dinger definitiv auch nicht parrallel ....

mach mal ne pause von paar msec rein, setz nen breakpoint :-) und schua dir das verhalten an ....

wie misst du die zeiten ? kann es sein das die ungenau sind ?

nurmal geht nix parallel, wenn du ned irgendwo explizit nen thread erstellst (QThread, oder CreateThread). Verwendest du ne bib die sowas machen koennte, wenn nein, brauchst auch keinen Mutex.

Aehm .....
Ich habe nun ein QMutex::lock am Anfang der Event-Funktion eingefügt, ein QMutex::unlock ans Ende eingefügt. Bei gleicher Triggerung: Deadlock! Bei 1 msec Unterschied zwischen den Triggerungen: OK!
kann es sein, das bei einer bestimmten bedingung innerhalb des 1. triggers, die funktion nochmal aufgerufen wird ? was zu deinem 2. trigger mit identischen zeiten fuehrt .... Schau dir die aufrufliste beim debuggen mal genau an !
IMHO die einzigste erklaerung die mir fuer den deadlock einfaellt .... also schau dir dosomething() noch mal genauer an ....
Und wie mein vorredner schon bemerkt, achte besonders auf events, die du verschickst oder die eventqueue zum abarbeiten zwingst. Imho sollte man sowas nie im gelockten zustand machen.

Ciao ...
Cartman
Beiträge: 55
Registriert: 31. März 2006 16:55

Beitrag von Cartman »

Hm... doSomething() rausnehmen, und die Triggerung scheint immer sequentiell zu sein. doSomething ist aber eine DLL-Funktion, die nur mit Win-Bordmitteln arbeitet, d. h. kein Qt. Ich habe keine Details/Sourcen zur Implementierung der DLL-Funktion.

Die DLL wird mit Win's LoadLibraryA während der Laufzeit geladen, dann werden mit GetProcAddress diverse Funktionpointer belegt. In einem simplen main-Beispiel mit sequentiellen Aufrufen der gewünschten DLL-Funktion funktioniert alles. Auch in der Loop mit 1000 Aufrufen.

Welche Erklärung bietet sich hier an?
Sephral
Beiträge: 201
Registriert: 1. Februar 2006 09:40
Kontaktdaten:

Beitrag von Sephral »

Die DLL-Funktion macht wohl irgendetwas was Qt dazu veranlasst seine Events abzuarbeiten (wie auch immer)...

Du könntest versuchen die Serialisierung der Aufrufe selbst zu übernehmen, wenn Du Dich in diesem Fall nicht auf QTimer verlassen kannst.

Einfach nen kleinen QThread der doSomething() aufruft.
Cartman
Beiträge: 55
Registriert: 31. März 2006 16:55

Beitrag von Cartman »

Ja, Sephral. Das mache ich direkt mal. Ich poste dann das Ergebnis, sobald verfügbar.
RHBaum
Beiträge: 1436
Registriert: 17. Juni 2005 09:58

Beitrag von RHBaum »

ubergibst du der dll zufaellig nen HWnd (Parent ... )oder sowas ?
dann verschickt die sicher window msg, worauf die QT mit events reagiert ...
bietet die dll irgendwie ne eigene GUI ? also baut selber fenster ?
kann es sein das die dll die winsocket benutzt ?

Ciao ...
Cartman
Beiträge: 55
Registriert: 31. März 2006 16:55

Beitrag von Cartman »

Ich übergebe nichts an die DLL, was verdächtig sein könnte. DependencyWalker zeigt mir WS2_32 und WSOCK32 durchaus an, ja. Die DLL-Funktionen kommunizieren eigentlich auch übers Netzwerk mit nem anderen Rechner. GDI32 erscheint auch. Ein eigenes Fenster geht im Hintergrund auf, nachdem LoadLibrary für die DLL ausgeführt wird (DLLMain oder so wird wohl mit Fensteröffnen implementiert sein, denke ich).
RHBaum
Beiträge: 1436
Registriert: 17. Juni 2005 09:58

Beitrag von RHBaum »

Wahrscheinlich checkt deine Dll ob neue daten angekommen sind mit dem was du ihr in dosomething machen laesst ... und wenn schon was im eingangspuffer ist, feuert sie gleich das event oder den callback oder was weiss ich was sie dir rausgibt, gleich nochmal, und du kommst nen 2 tes mal in deine eventqueue ....
oder reagierst du wirklich nur auf das timerevent ?
erzeugt die dll selber nen WM_Timer event ?

Also bevor ich mit multithreading da anfange, wuerd ich versuchen das lieber zu entkoppeln ...
musst du im dosomething unbedingt die dll sofort aufrufen?
oder kannst das entkoppeln irgendie ?

Ciao ...
Cartman
Beiträge: 55
Registriert: 31. März 2006 16:55

Beitrag von Cartman »

Hier sieht man noch schön die Timer-Ids der Timer-Events:

Code: Alles auswählen

begin 529, 16:11:42:438
begin 528, 16:11:42:438
doSomething error: can not set xyz to 0! error code -16397: "???"
end 528
end 529
Bei so einer Verschachtelung macht doSomething dann auch immer Fehler.

Ich hab mal nen QThread angelegt, das Laden der DLL in run() ausgeführt, anschließend exec() für die Abgabe der Programmsteuerung des Threads an die EventLoop des Threads.

Nach einem QThread::start von außen lasse ich doSomething per Signal durch die neue EventLoop des neuen Threads ausführen. Das Laden der DLL dauert nun ziemlich lang, jedoch ohne Fehler. Auch die Funktionen sind ansprechbar, ohne daß ein Fehlercode zurückkommt. Einen Effekt (Kommunikation zu Rechner B) erhalte ich dabei jedoch nicht.

Nun gut, das ganz war eh ein wenig "hacky".
Also bevor ich mit multithreading da anfange, wuerd ich versuchen das lieber zu entkoppeln ...
Hm. Unter Entkoppelung stelle ich mir zuerst eine Trennung in zwei Prozesse vor, die dann über Sockets, Pipes oder OS-Nachrichten kommunizieren. Das würd sicher funzen. Mit QProcess könnt ich mal was versuchen...
Antworten