Hallo!
Ich habe in meinem Programm mehrere Threads, die permanent laufen und
XML-Daten liefern. Diese Daten muss ich einer MS
SQL-Datenbank hinzufügen. Da es sich beim Datenbankserver um einen Remoteserver handelt und das direkte Hinzufügen im selben Thread desen Ablauf verzögern könnte (was ich in meinem Fall unbedingt vermeiden muss), habe ich einen anderen Thread erstellt, der die Daten einsammelt und der
DB hinzufügt. Dafür habe ich zusätzlich noch eine TStringList erstellt, in der die für
DB bestimmte Daten landen. Alle Threads fügen die
XML-Daten dieser TStringList hinzu. Der
DB-Thread greift immer wieder auf diese Liste zu, prüft ob neue Daten vorhanden sind und wenn was neues gibt, leitet die Daten an die
DB weiter.
Problem: Einige Datensätze aus der TStringList landen doppelt in die Datenbenk, während einige gar nicht hinzufügt werden. Dabei konnte ich sicherstellen, dass es keine gleiche Daten in der TStringList gibt. Was mache ich falsch?
Liste für die Daten und CriticalSection:
Delphi-Quellcode:
...
var
lstDBData: TStringList;
csDBData: TCriticalSection;
So werden die Daten in die Liste hinzufügt:
Delphi-Quellcode:
...
csDBData.Enter;
try
lstDBData.Add(XMLData);
finally
csDBData.Leave;
end;
Thread, der die Daten verarbeitet:
Delphi-Quellcode:
type
TAddDataToDB =
class(TThread)
constructor Create(CreateSuspended: Boolean; AAllowUpdate: Boolean);
private
AllowUpdate: Boolean;
protected
procedure Execute;
override;
end;
constructor TAddDataToDB.Create(CreateSuspended: Boolean; AAllowUpdate: Boolean);
begin
inherited Create(CreateSuspended);
FreeOnTerminate := true;
AllowUpdate := AAllowUpdate;
end;
procedure TAddDataToDB.Execute;
var
ADO: TADOTable;
XMLDoc: IXMLDocument;
XMLRoot: IXMLNode;
begin
CoInitialize(
nil);
ADO := TADOTable.Create(
nil);
ADO.ConnectionString := '
Provider=SQLOLEDB.1;Password=' + DB_PASSWORD + '
;' +
'
Persist Security Info=True;User ID=' + DB_USERNAME + '
;' +
'
Initial Catalog=' + DB_NAME + '
;' +
'
Data Source=' + DB_HOST;
ADO.TableName := DB_TABLE;
while not Terminated
do
begin
if lstDBData.Count > 0
then
begin
ADO.Active := true;
repeat
if Length(lstDBData.Strings[0]) > 0
then
begin
//Hier wird XML analysieret, zerteilt und in der DB hinzufügt
end;
//Verarbeite Daten aus der Liste entfernen
csDBData.Enter;
try
lstDBData.Delete(0);
finally
csDBData.Leave;
end;
until lstDBData.Count = 0;
ADO.Active := false;
end;
Sleep(10);
end;
ADO.Free;
end;