Autor |
Beitrag |
TomyN
Beiträge: 32
Erhaltene Danke: 2
Win10
D5 Std., Turbo-Delphi (w32), Delphi 2010
|
Verfasst: Mo 28.04.14 22:26
Hallo,
ich habe in meiner Anwendung einen Thread, der so aussieht:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28:
| implementation uses ocpData, windows, uAsioVars, AudioTools;
procedure TAsioOutThread.Execute; var eh: Array [0..1] of THandle; begin eh[0]:= outEvent; eh[1]:= closeEvent; repeat if waitForMultipleObjects(2, @eh[0], FALSE, 500) = wait_object_0 then begin if (driverState = 4) then begin enterCriticalSection(outSync); try if assigned(dpOut) then outCallBackEx(dpOut, puffersize, outMode); finally leaveCriticalSection(outSync); end; end; end; until terminated; end;
end. |
Im 'Normalbetrieb' wird der Thread regelmässig mit dem outEvent versorgt und führt dann die Routine OutcallBackEX aus. Das funktioniert unter winXP und win7 (Vista nicht getestet) wunderbar, unter win8.1 wird der Thread genau einmal ausgeführt. Wenn ich die Routine auskommentiere, dann kommt der Event regelmässig an.
Parallel läuft ein zweiter Thread für den Input, auch Event gesteuert, der funktioniert ohne Probleme, allerdings ohne den Aufruf eine Procedur, sondern nur mit Mathe und Api-Funktionen, aber auch mit Globalen Variablen.
Hat irgendwer eine Idee oder einen Tip, wo ich suchen kann?
Moderiert von Martok: Code- durch Delphi-Tags ersetzt
|
|
jaenicke
Beiträge: 19284
Erhaltene Danke: 1742
W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Mo 28.04.14 22:36
TomyN hat folgendes geschrieben : | unter win8.1 wird der Thread genau einmal ausgeführt |
Was heißt denn das? Bleibt der Thread dann hängen? Oder wird er beendet?
Wenn er hängen bleibt, sollten die Stacktraces der Threads Aufschluss geben was passiert. Dann sähe das sehr nach einem Deadlock aus, sprich zwei Threads warten gegenseitig auf eine Form der Synchronisierung (Synchronize, Critical Section, Event, ...).
Wenn Delphi auf dem entsprechenden PC läuft, brauchst du nur, sobald es hängt, auf Pause zu gehen und in der Threadliste alle Threads durchgehen und ihre Stacktraces anschauen.
|
|
TomyN
Beiträge: 32
Erhaltene Danke: 2
Win10
D5 Std., Turbo-Delphi (w32), Delphi 2010
|
Verfasst: Mo 28.04.14 22:45
Hi,
leider läuft Delphi nicht auf dem Rechner.
Ich habe schon die folgenden Tests gemacht:
- Eintrag ins Logfile nach dem EnterCriticalSection
- Eintrag ins Logfile nach dem LeaveCriticalSection
- Eintrag nach dem Until
Fazit:
Es kommt genau einmal Enter + Leave, Terminate (nach Until) genau dann wann es soll (wenn der Thread beendet wird). Lasse ich die Procedure raus (habe also nur noch Enter + Leave), dann kommen die Einträge regelmässig.
Der einmalige durchlauf kommt genau einmal nach dem Erzeugen + Start des Threads (der Thread wird Resumed erzeugt, und dann einmalig mit Start gestartet)
Tomy
|
|
jaenicke
Beiträge: 19284
Erhaltene Danke: 1742
W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Di 29.04.14 10:32
Das kann ja nur heißen, dass deine beiden if-Bedingungen nicht beide erfüllt sind und das Programm daher dort nicht ankommt.
Am besten loggst du einmal an dem Punkt, an dem DriverState und deine Events gesetzt werden und das Ergebnis der if-Abfragen im Thread. So solltest du ja herausbekommen ob das Setzen oder das Empfangen im Thread schief geht.
Rein ins Blaue geraten würde ich vermuten, dass das Setzen nicht oder nicht korrekt passiert.
|
|
TomyN
Beiträge: 32
Erhaltene Danke: 2
Win10
D5 Std., Turbo-Delphi (w32), Delphi 2010
|
Verfasst: Di 29.04.14 20:17
So,
nun hab ich das Problem gefunden. Es lag natürlich wieder woanders, und zwar im outCallbackEX.
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17:
| var pi: pLongInt; pd: double; Faktor: double; i: integer;
.... out_32: begin faktor:= $7FFFFFFF * siglatch.Laut; pi:= speicher; for i:=1 to Zahl do begin pi^:= round(faktor * pd^); inc(pD); inc(pi); end; end; .... |
blieb unter win8.1 beim ersten Schleifendurchlauf bei pi^:= round(Faktor * pd^) kommentarlos hängen.
Die Lösung ist:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9:
| out_32: begin faktor:= $7FFFFFFF * siglatch.Laut; pi:= speicher; for i:=1 to Zahl do begin pi^:= longInt(round(faktor * pd^)); inc(pD); inc(pi); end; end; |
Nach viel Grübeln kann man das sicherlich irgendwie erklären, aber weder die Typprüfung im Compiler noch Eurekalog haben das irgendwie angemault.. .
Vielen Dank für die Unterstützung
Tomy
Moderiert von Martok: Code- durch Delphi-Tags ersetzt
|
|
|