Autor |
Beitrag |
Gausi
      
Beiträge: 8548
Erhaltene Danke: 477
Windows 7, Windows 10
D7 PE, Delphi XE3 Prof, Delphi 10.3 CE
|
Verfasst: Di 13.04.10 18:36
Ich hab da eine kleine Verständnisfrage zu Semaphoren. Ich habe eine Workerthread-Klasse, die 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:
| type TCoverDownloadWorkerThread = class(TThread) private fSemaphore: THandle; end;
constructor TCoverDownloadWorkerThread.Create; begin fSemaphore := CreateSemaphore(Nil, 0, maxInt, Nil); end;
procedure TCoverDownloadWorkerThread.Execute; begin While Not Terminated do begin if (WaitforSingleObject(fSemaphore, 1000) = WAIT_OBJECT_0) then if not Terminated then begin machwas; end; end; end; |
Ich erzeuge also eine Semaphore, und warte darauf, dass da was passiert, bevor der eigentliche Thread anfängt zu arbeiten. Wenn was zu tun ist, rufe ich von der VCL aus das auf:
Delphi-Quelltext 1: 2: 3: 4:
| procedure TCoverDownloadWorkerThread.StartWorking; begin ReleaseSemaphore(fSemaphore, 1, Nil); end; |
Von meinem Verständnis her habe ich damit einen Thread, der schön im Hintergrund schlummert, bis er angestoßen wird oder terminieren soll.
Jetzt sieht das im Ereignisprotokoll aber so aus, als würden da ständig neue Threads laufen. Mach ich da was falsch, oder ist das normal so? D.h. die ID des Worker-Threads wechselt bei so einer Anwendung?
Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15:
| Thread-Start: Thread-ID: 4064. Prozess nemp.exe (3720) Thread-Ende: Thread-ID: 4064. Prozess nemp.exe (3720) Thread-Start: Thread-ID: 3012. Prozess nemp.exe (3720) Thread-Ende: Thread-ID: 3012. Prozess nemp.exe (3720) Thread-Start: Thread-ID: 1204. Prozess nemp.exe (3720) Thread-Ende: Thread-ID: 1204. Prozess nemp.exe (3720) Thread-Start: Thread-ID: 1364. Prozess nemp.exe (3720) Thread-Ende: Thread-ID: 1364. Prozess nemp.exe (3720) Thread-Start: Thread-ID: 3552. Prozess nemp.exe (3720) Thread-Ende: Thread-ID: 3552. Prozess nemp.exe (3720) Thread-Start: Thread-ID: 196. Prozess nemp.exe (3720) Thread-Ende: Thread-ID: 196. Prozess nemp.exe (3720) Thread-Start: Thread-ID: 2376. Prozess nemp.exe (3720) Thread-Ende: Thread-ID: 2376. Prozess nemp.exe (3720) // für jeden Job ein Thread, immer einer nach dem anderen |
_________________ We are, we were and will not be.
Zuletzt bearbeitet von Gausi am Di 13.04.10 21:06, insgesamt 2-mal bearbeitet
|
|
Kha
      
Beiträge: 3803
Erhaltene Danke: 176
Arch Linux
Python, C, C++ (vim)
|
Verfasst: Di 13.04.10 19:14
Gausi hat folgendes geschrieben : | Von meinem Verständnis her habe ich damit einen Thread, der schön im Hintergrund schlummert, bis er angestoßen wird oder terminieren soll. |
So würde ich es doch auch sehen. Von daher ist es halbwegs beruhigend, dass uns wenigstens der folgende Code Recht gibt  .
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: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40:
| program Project2;
{$APPTYPE CONSOLE}
uses SysUtils, Classes, Windows;
type TMyThread = class(TThread) public fSemaphore : THandle; constructor Create; protected procedure Execute; override; end;
constructor TMyThread.Create; begin inherited Create(True); fSemaphore := CreateSemaphore(nil, 0, MaxInt, nil); end;
procedure TMyThread.Execute; begin inherited; while WaitForSingleObject(fSemaphore, INFINITE) = WAIT_OBJECT_0 do Writeln('a'); end;
var t : TMyThread; begin t := TMyThread.Create; t.Start; while True do begin ReleaseSemaphore(t.fSemaphore, 1, nil); Sleep(1000); end; end. |
_________________ >λ=
|
|
Gausi 
      
Beiträge: 8548
Erhaltene Danke: 477
Windows 7, Windows 10
D7 PE, Delphi XE3 Prof, Delphi 10.3 CE
|
Verfasst: Di 13.04.10 19:31
Ok, der Code verhält sich bei mir auch nicht so.
Nachdem ich mal diese beiden Zeilen auskommentiert habe
Delphi-Quelltext 1: 2: 3:
| XMLData := fIDHttp.Get(url); fIDHttp.Get(BestCoverURL, DataStream); |
Ist das auch im Originalcode so.
Frage also: warum machen die Indys das so, und kann man das ggf. abstellen, falls das hier nicht sinnvoll ist? Der Download läuft ja schon in einem Nebenthread, da muss doch nicht noch einer gestartet werden. 
_________________ We are, we were and will not be.
|
|
Martok
      
Beiträge: 3661
Erhaltene Danke: 604
Win 8.1, Win 10 x64
Pascal: Lazarus Snapshot, Delphi 7,2007; PHP, JS: WebStorm
|
Verfasst: Di 13.04.10 19:34
_________________ "The phoenix's price isn't inevitable. It's not part of some deep balance built into the universe. It's just the parts of the game where you haven't figured out yet how to cheat."
|
|
Gausi 
      
Beiträge: 8548
Erhaltene Danke: 477
Windows 7, Windows 10
D7 PE, Delphi XE3 Prof, Delphi 10.3 CE
|
Verfasst: Di 13.04.10 19:48
Ok, dann ist das wohl so in Ordnung.
Zu den Events: Wie würde da denn das Grundgerüst aussehen? Was ich sonst in der Richtung Workerthread gesehen habe, arbeitet iirc auch mit einer Semaphore. Und der Delphi-TThread hat doch keine Nachrichtenschleife, in die ich was einhängen könnte, oder?
_________________ We are, we were and will not be.
|
|
Narses
      

Beiträge: 10183
Erhaltene Danke: 1256
W10ent
TP3 .. D7pro .. D10.2CE
|
Verfasst: Di 13.04.10 19:52
Moin!
Du suchst nicht sowas, oder?
cu
Narses
_________________ There are 10 types of people - those who understand binary and those who don´t.
|
|
Martok
      
Beiträge: 3661
Erhaltene Danke: 604
Win 8.1, Win 10 x64
Pascal: Lazarus Snapshot, Delphi 7,2007; PHP, JS: WebStorm
|
Verfasst: Di 13.04.10 20:03
@Narses: nein, meine ich nicht. Ich meine die Synchronisationsobjekte "Event". Obwohl man sicher auch TMessageThread für die Anwendung nehmen könnte... wäre zu überlegen.
Gausi hat folgendes geschrieben : | Zu den Events: Wie würde da denn das Grundgerüst aussehen? |
Fast genauso, nur dass man statt CreateSemaphore CreateEvent verwendet.
Und dann später SetEvent oder PulseEvent. Code hab ich auch irgendwo, ich kopier mal was raus... ah, okay, da war ein VCL-Fan am Werk. Unit SyncObjs.
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:
| FFeedEvent:= TEvent.Create(nil, true, false,''); FFeed:= TWOFeed.Create(Self, FFeedEvent);
if NochBufferDa then Verarbeiten; else begin FFeedEvent.SetEvent; exit; end;
procedure TWOFeed.Execute; var b: integer; begin b:= 0; while not Terminated do begin FEvent.WaitFor(100); FEvent.ResetEvent; try FOwner.Thread_SendFunc(b); except raise; end; end; end; |
Also quasi das Gleiche. Nur das Events wesentlich schneller sind, was die Zeit von SetEvent bis zum Zurückkehren von WaitFor* betrifft. Liegt unter anderem da dran, dass sie für dieses Thema gemacht sind.
Und wir reden hier IIRC von Mikrosekunden vs. Millisekunden.
_________________ "The phoenix's price isn't inevitable. It's not part of some deep balance built into the universe. It's just the parts of the game where you haven't figured out yet how to cheat."
|
|
Gausi 
      
Beiträge: 8548
Erhaltene Danke: 477
Windows 7, Windows 10
D7 PE, Delphi XE3 Prof, Delphi 10.3 CE
|
Verfasst: Di 13.04.10 20:17
Ah, ok. Wieder was gelernt.
Den MessageThread behalte ich mal im Hinterkopf, und diese Form der Events auch. Das sind also nicht die Events, die man an den Komponenten kennt, sondern globale Dinger, richtig?
Aber um Geschwindigkeiten mach ich mir hier aber keine Gedanken. Erstens soll der Thread was runterladen (erst eine kleine REST-Anfrage, dann ein kleines Bild, im Schnitt 50-100 kb). Der Flaschenhals liegt also ganz woanders. Und zweitens darf ich das sowieso nur maximal fünf mal pro Sekunde machen, sonst schimpfen die bei LastFM.
Aber ich probier das mal mit den Events aus, das scheinen ja nur ein paar kleine Änderungen zu sein, die ich da machen muss.
Edit: ich müsste dann ein if FEvent.WaitFor(100)=wrSignaled then... einbauen, wenn nur dann etwas getan werden soll, wenn das Event vorher ausgelöst wurde, oder?
Edit2: Ok, mit Events geht das genauso gut. Und wenn die für sowas da sind, dann lass ich das jetzt auch so. 
_________________ We are, we were and will not be.
|
|
|