Der Unterschied leigt, wie häufig in der
OOP, bei der Zuständigkeit: Den Thread hat es nicht zu interessieren, dass er "schlafen gelegt wird". Auch das Locking sollte nicht in seinen Zuständigkeitsbereich fallen.
Idealerweise ist diese Verhalten vollkommen transparent, etwa in der Form:
Delphi-Quellcode:
procedure TMyThread.Execute;
var
myItem: TMyClass;
begin
Assert(Assigned(FFifoData), 'FiFo-Buffer not assigned');
while not Terminated do
begin
myItem:= FFifoData.Pop;
DoSthWidth(myItem);
end;
end;
bzw
Delphi-Quellcode:
procedure TMyTread.AddItem(const AnItem: TMyClass);
begin
if not Assigned(AnItem) then
raise EItemNotAssignedError.Create(ItemNotAssigned);
Assert(Assigned(FFifoData), 'FiFo-Buffer not assigned');
FFifoData.Push(AnItem);
end;
Das Blockieren eines Clients (Aufrufer), der die Nachricht
Pop schickt, sowie dessen anschließende Fortsetzung, sobald ein Element dem Puffer hinzugefügt worden ist, übernimmt nach diesem Muster vollständig der Puffer.
Problematisch ist in diesem Zusammenhang lediglich der Fall, dass der Thread beendet werden soll, jedoch kein weiterer Eintrag im Puffer vorhanden ist. Hierfür könnte eine spezielle Methode des Puffers eingesetzt werden, der alle Consumer (den Thread) weckt, ohne ein Element als Rückgabewert von
Pop zur Verfügung zu stellen. Denkbar ist der Wurf einer Exeception
EBufferClosed, die dann in
Execute adequat behandelt werden sollte:
Delphi-Quellcode:
procedure TMyThread.Execute;
var
myItem: TMyClass;
begin
while not Terminated do
try
myItem:= FFifoData.Pop;
DoSthWidth(myItem);
except
on EBufferClosed do
Terminate;
end;
end;