Was für Listen genau hängt natürlich davon ab, was du für Daten hin und her schieben willst. Ich habe meist eine Hand voll kleiner Daten-Klassen, die die nötigen Infos aufnehmen, und werfe diese dann in meine Listen. Wenn es nur um Strings geht, ist eine StringList natürlich angenehm fertig.
Um den zweiten Teil zu erklären mal zwei Code-Fetzen:
Zum einen die "faule" Variante:
Delphi-Quellcode:
{uDataLists.pas}
TMyDataContainer = class
public
x, y, z: Integer;
end;
{uMyThread.pas}
TMyThread = class(TThread)
private
MainForm: THandle; // Im Konstruktor übergeben, dann kann das von PostMessage genutzt werden, und der Thread könnte jedes beliebige Form bedienen.
...
public
MainFormDataList: TList<TMyDataContainer>;
...
end;
{uMainForm.pas}
TMainForm = class(TForm)
private
ThreadDataList: TList<TMyDataContainer>;
MyThread: TMyThread;
...
public
...
end;
Und etwas netter:
Delphi-Quellcode:
{uDataLists.pas}
TMyDataContainer = class
public
x, y, z: Integer;
end;
{uThreadCommunications.pas}
TMyThreadToFormCommunicator = class
private
class var FFromFormToThread: List<TMyDataContainer>;
class var FFromThreadToForm: List<TMyDataContainer>;
class var FCriticalSection: TCriticalSection;
public
class procedure PutInFormToThread(aDataContainer: TDataContainer);
class function GetFromFormToThread: TDataContainer;
...
end;
class procedure TMyThreadToFormCommunicator.PutInFormToThread(aDataContainer: TDataContainer);
begin
FCriticalSection.Enter;
try
FFromFormToThread.Add(aDataContainer);
finally
FCriticalSection.Leave;
end;
end;
class function TMyThreadToFormCommunicator.GetFromFormToThread: TDataContainer;
begin
FCriticalSection.Enter;
try
if FFromFormToThread.Count > 0 then
begin
result := FFromFormToThread.Items[0];
FFromFormToThread.Remove(result);
end
else
result := nil;
finally
FCriticalSection.Leave;
end;
end;
{uMyThread.pas}
TMyThread = class(TThread)
private
MainForm: THandle; // Im Konstruktor übergeben, dann kann das von PostMessage genutzt werden, und der Thread könnte jedes beliebige Form bedienen.
...
public
...
end;
procedure TMyThread.Execute;
begin
repeat
try
if FormNeedsUpdate then
begin
TMyThreadToFormCommunicator.PutInThreadToForm(currentDataContainer);
PostMessage(FMainForm, WM_THREADUPDATE, 0, 0);
end;
if TMyThreadToFormCommunicator.FromFromToThreadCount > 0 then
begin // Ob man hier immer nur ein Element verarbeitet oder sofort alle anstehenden ist Ermessenssache und vom genauen Zweck anhängig
dataContainer := TMyThreadToFormCommunicator.GetFromFromToThread;
DoStuffWith(dataContainer);
dataContainer.Free;
end;
Sleep(1); // CPU Zeit abgeben um 100%-Auslastung in ruhigen Phasen zu vermeiden
except
// Allgemeine Exceptionbehandlung
end;
until Terminated;
end;
// Thread nutzt dann TMyThreadToFormCommunicator.PutInThreadToForm() und TMyThreadToFormCommunicator.GetFromFormToThread
{uMainForm.pas}
TMainForm = class(TForm)
private
MyThread: TMyThread;
procedure ThreadUpdateHandler(var Msg: TMessage); message WM_THREADUPDATE;
...
public
...
end;
procedure TMainForm.ThreadUpdateHandler(var Msg: TMessage);
var
dataContainer: TMyDataContainer;
begin
dataContainer := TMyThreadToFormCommunicator.GetFromThreadToForm;
DoStuffWith(dataContainer);
dataContainer.Free;
end;
// Form nutzt dann TMyThreadToFormCommunicator.PutInFormToThread() und TMyThreadToFormCommunicator.GetFromThreadToForm
Die Datencontainerklassen müssen natürlich nicht identisch sein, ich wollte es nur nicht noch länger machen. Bei der faulen Variante halst man sich ggf. im Nachgang mehr Arbeit auf, da die gesamte Synchronisation noch passieren muss. Alternativ erstellt man sich eine generische Listenklasse, die von sich aus alle Zugriffe synchronisiert. Das sieht nach einem Haufen Vorbau aus, erspart einem später aber Ärger mit der Sync und ist im Handling dann später wirklich geschmeidig. Dieser Weg erhebt aber keinen Anspruch auf Allgemeingültigkeit, es gibt sicherlich Szenarien, in denen das völlig verkehrt sein kann. Bei mir passte eine solche oder ähnliche Struktur halt sehr oft ins Konzept.
"When one person suffers from a delusion, it is called insanity. When a million people suffer from a delusion, it is called religion." (Richard Dawkins)