frage zu threads und timer
hi
ich arbeite mal wieder an meinen Bass(.dll) komponenten, die komponenten sind mittlerweile so kompliziert geworden dass es immer schwieriger wird die zu managen! zum beispiel die Sound-Recorder komponente, die hat vier haupt threads(feeder) und wenn einer der threads zu schnell oder zu langsam ist bricht das ganze zusammen. und hier komme ich auch gleich zu meiner frage. was ist die eleganteste lösung um threads oder das innenleben:wink: perfect zu takten? zur zeit benutze ich zwei verschieden methoden Sleep(x) und TSimpleEvent. vielleicht hat einer von euch noch einen dritten vorschlag für den unteren code, das timing muss 100% präzise sein damit der buffer nicht lehr läuft.
Delphi-Quellcode:
procedure TBassRecorder.RecThreadWorkerCallback(Thread: TMultiThreadThread;
Parameters : TObject; var Data, Results : TObject); var FBuff : array [0..50000] of Byte; FData : DWORD; WorkMessage: TWorkMessage; WorkResult: TWorkResult; begin WorkMessage := TWorkMessage.Create; WorkMessage.ID := TWork(Data).ID; WorkMessage.Text := 'Starting'; WorkMessage.Status:= thStarting; Thread.SendMessage(WorkMessage, nil); repeat Sleep(TWork(Data).TimeToWait); //TimeToWait = 1 if not ThreadPause[THREAD_REC] then begin FData:= BASS_ChannelGetData(Channel[CHANN_REC_MIXER], @FBuff, SizeOf(FBuff)); if FData = DW_ERROR then begin Break; // Error end; end; until Thread.Terminated or (Channel[CHANN_REC_MIXER] = 0); if Thread.Terminated then begin WorkMessage := TWorkMessage.Create; WorkMessage.ID := TWork(Data).ID; WorkMessage.Text := 'Terminated'; WorkMessage.Status:= thTerminated; Thread.SendMessage(WorkMessage, nil); end; WorkResult := TWorkResult.Create; WorkResult.ID := TWork(Data).ID; WorkResult.Text := 'Finished'; //finished successfuly. WorkResult.Status:= thFinished; Results := WorkResult; end;
Delphi-Quellcode:
procedure TBassRecorder.VasThreadWorkerCallback(Thread: TMultiThreadThread; Parameters: TObject; var Data, Results: TObject);
var Time : QWORD; Level : DWORD; Active : Boolean; Timer: TWaitResult; WorkMessage : TWorkMessage; WorkResult : TWorkResult; begin WorkMessage := TWorkMessage.Create; WorkMessage.ID := TWork(Data).ID; WorkMessage.Text := 'Starting'; WorkMessage.Status:= thStarting; Thread.SendMessage(WorkMessage, nil); repeat if not ThreadPause[THREAD_VAS] then begin Level:= BASS_Mixer_ChannelGetLevel(Channel[CHANN_VIS_SPLIT]); Active:= (LOWORD(Level) >= FVAS_Threshold) or (HIWORD(Level) >= FVAS_Threshold); (* sound is coming through *) if Active then begin (* continue recording when the sound starts up again. *) ... (* start a new recording ehen the sound starts up again. *) ... end; Timer:= TWork(Data).TimeEvent.WaitFor(TWork(Data).TimeToWait); // 1000 = 1 Sec. if Timer = wrTimeout then begin (* sound is not coming through *) if not Active then begin (* Pause Recording after X Sec. of silence *) ... (* Pause Recording after X Sec. of silence *) ... (* Stop Recording after X Sec. of silence *) ... end; end; end; until (FVAS_ForceStop) or (Timer <> wrTimeout) or (Thread.Terminated) or (Application.Terminated); if Thread.Terminated then begin WorkMessage := TWorkMessage.Create; WorkMessage.ID := TWork(Data).ID; WorkMessage.Text := 'Terminated'; WorkMessage.Status:= thTerminated; if Assigned(TWork(Data).TimeEvent) then TWork(Data).TimeEvent.SetEvent; Thread.SendMessage(WorkMessage, nil); end; WorkResult := TWorkResult.Create; WorkResult.ID := TWork(Data).ID; WorkResult.Text := 'Finished'; //finished successfuly. WorkResult.Status:= thFinished; if Assigned(TWork(Data).TimeEvent) then TWork(Data).TimeEvent.SetEvent; Results := WorkResult; end; |
AW: frage zu threads und timer
Ohne jetzt genau deinen Code zu betrachten: Definitiv Events! Sleep ist extrem unzuverlässig. Du kannst als WaitTime auch die Konstante INFINITE verwenden. Dann wartet der Thread solange, bis vom anderen Thread aus das Event signalisiert wird.
Ich denke du solltest dich generell in den Themenkomplex "Threadsynchronisierung" mal etwas einlesen. CriticalSections könnten auch eine Möglichkeit sein konkurrierende Zugriffe auf den Buffer zu managen. |
AW: frage zu threads und timer
Stell Dir einfach vor, deine 4 Threads sind 4 Personen, die gleichzeitig irgend etwas machen, vermutlich in einer Schleife.
Also: 1 Koch, der auf Bestellungen wartet, diese zubereitet und dann in der Durchreiche abstellt und vermutlich irgend eine Bimmel betätigt. 1 Gast, der Platz nimmt, Hunger bekommt oder hat, auf einen Ober wartet, eine Bestellung aufgibt, auf das Essen wartet, isst, rülpst, bezahlt und geht. 1 Ober, der Bestellungen vom Gast aufnimmt, diese zur Küche bringt und (wie?) an die Küche übermittelt. 1 Ober, der die fertig gekochten Gerichte aus der Küche zum Gast bringt, abräumt und ggf. abkassiert. 1 Inhaber, der blöd in der Ecke rumhängt, sich einen Cocktail nach dem anderen hinter die Binde knallt und mit der Barfrau schäkert. Gut, der letzte muss jetzt nicht synchronisiert werden, aber da kann man lernen, das es Threads gibt, die Überflüssig wie ein Kropf sind. Was ich meine sind die Schnittstellen zwischen den Threads: Würde der Koch nach dem Kochen eines Gerichts warten, bis dieses abgeholt wird, würden sich die Bestellungen vermutlich stapeln, oder man bräuchte mehrere Köche. Er könnte auch alle paar Sekunden zur Bestellannahme gehen und schauen, ob es was neues zu tun gibt. Besser, aber auch blöd, weil er dann auch mal umsonst schauen geht. Was ist also der beste Weg? Wenn der Ober so lange vor dem Gast auf und ab wippt, bis dieser sich entschieden hat, ist das auch keine gute Sache, denn der Gast wird dem Ober vermutlich irgendwann eins mit der Karte übersemmeln oder gleich zum Inhaber gehen, der dann doch eine gewisse Funktion hat... Die Lösung ist die 'asynchrone Kommunikation' (Bimmel, 'Her Ooober', 'Zahlen bitte') sowie Queues (Essensausgabe, Bon-Leiste usw). Lustig ist, das in einem Restaurant ein Restaurantleiter etwaige Staus auflöst und für einen reibungslosen Ablauf sorgt. Ein ähnlicher Controller würde in kritischen Systemen die Threads und Übergaben auch überwachen (overflows etc.) und ggf. eingreifen. Ein Thread reagiert auf Events, und löst selber Events aus, wenn er einem anderen Thread mitteilen will, das dieser weiterarbeiten kann. Der Thread nimmt Aufträge aus einer Queue, führt diese aus und schreibt sein Ergebnis wieder in eine Queue usw. Der Controller prüft die Queues und reagiert, wenn diese so groß werden: Dann ist ein Thread entweder abgeschmiert (gaaanz schlecht) oder kommt mit der Arbeit einfach nicht hinterher (zweiten Thread starten: Fertig). Oder das System ist dann einfach überlastet: Eine Küche mit zwei Herden (=limitierte Resourcen) ist auch mit 20 Köchen nicht in der Lage, mehr als 30 Personen zu bewirten... |
AW: frage zu threads und timer
danke für die schnelle antwort.
über die Sleep funktion hatte ich mir auch schon gedanken gemacht das die vielleicht nicht die beste lösung ist. und dass mit der INFINITE Konstante macht in meinem fall keinen sinn. ich habe für jeden thread drei verschiedene Callback funktionen die mir genau sagen wann und was abgeht; und somit kann ich auf die anderen threads reagieren. mir ging es hauptsächlich ums perfect timing from within the loop.
Delphi-Quellcode:
procedure TBassRecorder.RecThreadWorkerCallback(Thread: TMultiThreadThread;
Parameters : TObject; var Data, Results : TObject); begin // main thread wo sehr hart gearbeitet wird end; procedure TBassRecorder.VasThreadResultsCallback(Sender: TObject; var Data, Results: TObject); var WorkResult: TWorkResult; begin WorkResult := TWorkResult(Results); if WorkResult.Status = thFinished then begin ThreadFinished[THREAD_VAS]:= True; end; end; procedure TBassRecorder.VasThreadMessage(Sender: TObject; var Message1, Message2: TObject); begin // test if TWorkMessage(Message1).Status = thStarting then begin ThreadFinished[THREAD_VAS]:= False; end; if TWorkMessage(Message1).Status = thTerminated then begin ThreadFinished[THREAD_VAS]:= True; end; end; wie schon gesagt das ding ist ein kompliziertes monster geworden. aber ich denke ich habe die meisten fehler ausgemerzt. natürlich muss ich das ganze auch auf anderen Systemen testen. hat nichts mit dem thema zutun aber rein theoretisch, welche features würdet ihr euch in ein Sound-Recorder wünschen thanks again for your help. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 05:50 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz