Mam pytanko. Napisałem program, który w oparciu o timer pobiera pewne informacje z bazy, a następnie wysyła je na e-mail. Wewnątrz procedury tworzę dynamicznie dwa query (zeos), które pobierają dane z bazy. Program działa bez zarzutu, jednak gdy uruchomię tą samą procedurę w klasie TThread to sypie accesami na prawo i lewo. Domyślam się, że gdzieś odnoszę się do wątku, który już nie istnieje, jednak nie umiem tego namierzyć. Moglibyście rzucić okiem?
procedure TfrmMain.timStartTimer(Sender: TObject);
var
ind: integer;
sqlZap: string;
sList: TStringList;
begin
qLST_ZAD.Close;
qLST_ZAD.Open;
qLST_ZAD.First;
try
sList := TStringList.Create;
while not qLST_ZAD.Eof do
begin
try
if not sList.Find(qLST_ZAD.FieldByName('idx_zadania').asstring, ind) then
begin
TStartEvent.Create(qLST_ZAD.FieldByName('idx_zadania').AsInteger);
// WysWiad(qLST_ZAD.FieldByName('idx_zadania').AsInteger); //jak wywołuję samą procedurę bez wątku to jest ok
sList.Add(qLST_ZAD.FieldByName('idx_zadania').AsString);
sList.Sort;
end;
qLST_ZAD.Next;
except
sqlZap := 'mailing.log_dodaj(' + #39 + 'Nie udało się uruchomić zadania nr: '+
qLST_ZAD.FieldByName('idx_zadania').AsString + #39 + ', ' +
'1);';
OpenSQL(sqlZap);
end;
end;
finally
sList.Free;
end;
end;
i procedura z wątku:
constructor TStartEvent.Create(id: Integer);
begin
inherited Create(False); // wywołanie wątku
Fid := id; // przypisanie wartości do zmiennej
end;
procedure TStartEvent.Execute;
begin
FreeOnTerminate := True; // zwolnij po zakończeniu wątku
WysWiad(Fid);
end;
procedure WysWiad(id: integer);
var
q, qZ: TZQuery;
sqlZap, tmp, msg_tmp, gDef: string;
lEmail: TEmail;
Freq, TimeStart : Int64;
begin
//główna procedura systemu
try
QueryPerformanceCounter(TimeStart); // myslalem poczatkowo ze to wina nazwy
qZ := TZQuery.Create(frmMain);
qZ.Name := 'qZ' + FloatToStr(TimeStart); //unikalna nazwa dla kazdego watka
qZ.Connection := frmMain.db;
qZ.SQL.Text := 'SELECT idx_znacznika, znacznik, pole FROM mailing.znaczniki';
qZ.Open;
gDef := frmMain.AfOpen(qZ); //tu jest petla while po calym query ktore zwraca stringa np w postaci np: "u.IMIE "Imie", u.NAZW "Nazwisko" itd ...
q := TZQuery.Create(frmMain);
q.Name := 'qTMP' + FloatToStr(TimeStart);
q.Connection := frmMain.db;
q.SQL.Text := SQL_Select + gDef + SQLForm;
q.ParamByName('id').AsInteger := id; //id przekazany z timera
try
q.Open;
if q.RecordCount = 0 then
Exit;
except
sqlZap := 'mailing.log_dodaj(' +#39+ 'Błąd parametów w zapytaniu SQL: ' + q.SQL.Text + #39+ ', 1);';
OpenSQL(sqlZap);
Exit;
end;
q.First;
while not q.Eof do
begin
qZ.First;
msg_tmp := q.FieldByName('tresc').AsString;
if qZ.RecordCount > 0 then
begin
while not qZ.Eof do
begin
tmp := Copy( qZ.FieldByName('pole').AsString,
Pos('"', qZ.FieldByName('pole').AsString)+1,
PosEx('"', qZ.FieldByName('pole').AsString, Pos('"', qZ.FieldByName('pole').AsString)+1) - Pos('"', qZ.FieldByName('pole').AsString)-1
);
if tmp <> '' then
begin
msg_tmp := StringReplace(msg_tmp,
qZ.FieldByName('znacznik').AsString,
q.FieldByName(tmp).AsString,
[rfReplaceAll]);
end
else
msg_tmp := StringReplace(msg_tmp,
qZ.FieldByName('znacznik').AsString,
qZ.FieldByName('pole').AsString,
[rfReplaceAll]);
qZ.Next;
end;
end;
if ((StrToTime(q.FieldByName('start_od').AsString) <= Time) and
(StrToTime(q.FieldByName('start_do').AsString) >= Time)) then
begin
msg_tmp := StringReplace(msg_tmp, #39, '', [rfReplaceAll]);
if msg_tmp <> '' then
TEmail.Create(q.FieldByName('mail').AsString,
q.FieldByName('temat').AsString,
msg_tmp,
q.FieldByName('idx_maila').AsInteger); //tu inny TThread ale z nim raczej nie ma problemu bo sypie sie wczesniej
end;
q.Next;
end;
if ((q.RecordCount > 0) and (msg_tmp <> '')) then
begin
sqlZap := 'mailing.zadania_start(' + IntToStr(id) + ', ' +
BoolToStr(TRUE,True) + ');';
StrToBool(OpenSQL(sqlZap)); //zaktualizowaliśmy pole start więc timer nie będzie więcej wyszukiwał tego zadania
end;
finally
q.Free;
qZ.Free;
end;
end;