Registriert seit: 15. Jan 2006
Ort: Das schöne Enger nahe Bielefeld
809 Beiträge
Delphi XE Professional
|
Re: Ist SetLength Thread-safe?
25. Okt 2009, 10:03
Guten Morgen!
Hier mal ein kleines Beispiel, so zusammengetippt und ohne Anspruch auf irgendetwas, aber es sollte die Benutzung von CriticalSections zeigen, ausserdem gibt es noch ein Event, um der Form bescheid zu sagen. Hoffe, hier sind nicht allzuviele Böcke drin ..
Delphi-Quellcode:
interface
type
TMyArray = array of string;
TDataThread = class(TThread)
private
FOnNotify: TNotifyEvent;
FArray: TMyArray;
procedure DoNotify;
protected
procedure Execute; override;
public
constructor Create(Arr: TArray);
property OnNotify: TNotifyEvent read FOnNotify write FOnNotify;
end;
TMyForm = class(TForm)
private
ThreadA: TDataThread;
ThreadB: TDataThread;
procedure ThreadNotify(Sender: TObject);
public
constructor Create(AOwner: TComponent);
end;
var
CS: TCricicalSection;
implementation
constructor TDataThread.Create(Arr: TMyArray);
begin
inherited Create(True);
FArray := Arr;
end;
procedure TDataThread.Execute;
var
i: Integer;
FTempArray: TArray;
begin
SetLength(FTempArray, 0);
while True do
begin
// Mache ganz viel. Befülle das FTempArray.
// Wenn FTempArray "voll" ist, wird
// die CS betreten, das echte Array manipuliert,
// Der Form bescheid gesagt, und dann geht es weiter.
// Einen gesammelten Datensatz dem internen Array hinzufügen
SetLength(FTempArray, Length(FTempArray) + 1);
FTempArray[High(FTempArray)] := 'asdf';
if Length(FTempArray > 100)
begin
CS.Enter; // Zugriff global absichern
SetLength(FArray, Length(FArray) + Length(FTempArray));
for i := 0 to Length(FTempArray) do // kA ob Schleife so passt, ist noch zu früh.
FArray[Length(FArray) - Length(FTempArray) + i] := FTempArray[i];
CS.Leave; // Und Zugriff wieder erlauben
Synchronize(DoNotify); // Und der Form bescheid sagen, dass neue Daten da sind
end;
SetLength(FTempArray, 0);
end;
end;
procedure TDataThread.DoNotify;
begin
if Assigned(FOnNotify)
FOnNotify(Self);
end;
constructor TMyForm.Create(AOwner: TComponent);
begin
inherited;
SetLength(FArray, 0);
CS := TCriticalSection.Create;
ThreadA := TDataThread.Create(FArray);
ThreadA.OnNotify := ThreadNotify;
ThreadA.Resume;
ThreadB := TDataThread.Create(FArray);
ThreadB.OnNotify := ThreadNotify;
ThreadB.Resume;
end;
procedure TMyForm.ThreadNotify(Sender: TObject);
begin
// Thread hat Datenblock gesammelt, hier könnte
// man jetzt auf das Array zugreifen, ganz bequem.
// Wichtig ist hier auch die CriticalSection und
// man sollte zusehen, dass das, was man hier macht,
// ganz schnell geht, weil ein Thread, der sein
// internes Array voll hat und die Daten übertragen
// möchte das bis zum CS.Leave nicht kann.
CS.Enter;
ShowMessage(FArray[0]);
CS.Leave;
end;
|
|
Zitat
|