![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Thread (проблема завершения 3 потока) [D6, WinXP]
kaharin © (2007-08-30 23:44:00)Суть проблемы в следующем
есть основной поток (1) из него запускается дополнительный поток (2) который собирает данные из базы (список транзакций для отправки). Так как транзакции должны уходить в разные места то во втором потоке динамически создаются еще n.. количество потоков (до 50) и они отпускаются в свободное плаванье (не пересекаясь). Так вот если я останавливаю по флагу поток номер 2 то у меня какая то часть динамических потоков как бы вылетают (перестают работать) Вопрос если у потоков такое понятие как "папа" и если да то как сделать так что у динамических потоках папа был не создатель потока а основной поток программы
пример кода:
запуск 2 потока
procedure TSQL.Execute;
var
Goend_flag:boolean;
label Pause;
label Work;
label Goend;
label Start;
begin
RaningPotoks:=0;
while not Terminated do
begin
try
fMonDirMain.TOPUP_Query.Close;
fMonDirMain.TOPUP_Query.Open;
Goend_flag:=false;
except
fMonDirMain.lbLog.Items.Add('Îøèáêà ïðè îáðàùåíèè ê áàçå äàííûõ');
Goend_flag:=true;
end;
if Goend_flag=true then goto Goend;
RecordsInZapros:=fMonDirMain.TOPUP_Query.RecordCount;
if fMonDirMain.lbLog.Items.Count > 100 then fMonDirMain.lbLog.Items.Clear;
if not fMonDirMain.TOPUP_Query.IsEmpty then
begin
fMonDirMain.TOPUP_Query.DisableControls;
fMonDirMain.TOPUP_Query.First;
While not (fMonDirMain.TOPUP_Query.Eof) do
begin
if stop=true then
BEGIN
fMonDirMain.TOPUP_Query.EnableControls;
fMonDirMain.TOPUP_Query.Close;
Application.ProcessMessages;
self.Terminate;
exit;
END;
if RaningPotoks = MaxThread then goto Pause else goto Work;
Pause:
repeat
Application.ProcessMessages;
Sleep(100);
if stop=true then
begin
fMonDirMain.TOPUP_Query.EnableControls;
self.Terminate;
exit;
end;
until (RaningPotoks < MaxThread);
Work:
RaningPotoks:=RaningPotoks+1;
fMonDirMain.sbMain.Panels[3].Text:='Àêòèâíû 229; çàïðîñû: '+IntTOStr(RaningPotoks);
Sleep(100); // создание и запуск динамических потоков TMonDirThread.Create(fMonDirMain.TOPUP_Query.FieldByName('PK_PAYMENT_ID').AsStri ng, //id
fMonDirMain.TOPUP_Query.FieldByName('SYSTEM_REF').AsString, // êîä óñïåøíîãî ïëàòåæà
fMonDirMain.TOPUP_Query.FieldByName('FK_TOPUP_REQUEST_CODE').AsString, // êîä îøèáêè ïðîâàéäåðà ïðè ïðîâåäåíèè
fMonDirMain.TOPUP_Query.FieldByName('FK_TOPUP_RESULT_ID').AsString, // êîä ïëàòåæà â áàçå ïðîâàéäåðà
fMonDirMain.TOPUP_Query.FieldByName('FK_SUPPLIER_ID').AsString, // êîä òåðìèíàëà
fMonDirMain.TOPUP_Query.FieldByName('FK_PROVIDER_ID').AsString, // êîä ïðîâàéäåðà
fMonDirMain.TOPUP_Query.FieldByName('SYSTEM_TIME_END').AsString, // äàòà îêîí÷àíèÿ óñïåøíîãî ïðîâåäåíèÿ
fMonDirMain.TOPUP_Query.FieldByName('AMOUNT').AsString, //ñóììà âíåñåííûõ äåíåã
fMonDirMain.TOPUP_Query.FieldByName('SUM_COMMISSION').AsString, // ñóììà êîìèññèè
fMonDirMain.TOPUP_Query.FieldByName('ACCOUNT_NUMBER').AsString, // èíäèôèêàòîð1
fMonDirMain.TOPUP_Query.FieldByName('CONTRACT_NUMBER').AsString, // èíäèôèêàòîð2
fMonDirMain.TOPUP_Query.FieldByName('CONTACT_DETAILS').AsString, // èíäèôèêàòîð3
fMonDirMain.TOPUP_Query.FieldByName('FIO').AsString, // // èíäèôèêàòîð4 èëè ÔÈÎ
fMonDirMain.TOPUP_Query.FieldByName('MONTH_YEAR').AsString, // îïëàòà çà ïåðèóä
fMonDirMain.TOPUP_Query.FieldByName('SLIP_ID').AsString, // íîìåð ÷åêà
fMonDirMain.TOPUP_Query.FieldByName('SLIP_TIME').AsString){)}; // äàòà ÷åêà
fMonDirMain.TOPUP_Query.Next;
end;
fMonDirMain.TOPUP_Query.EnableControls;
end;
Goend:;
end;
evvcom (2007-09-03 14:31:00) [1]
> для освобождения ReleaseSemaphore - а по подробней плиз
А книжку умную почитать? Или тебе ее сюда выложить?
Про потоки почитай, про синхронизацию, примеры разбери, что бывает, когда нет синхронизации, а потом подумай, а заточена ли VCL под мультипоточность?
Сергей М. (2007-09-03 14:28:00) [2]
> TMonDirThread(self)
Это зачем ?
Slym (2007-09-03 14:17:00) [3]1. TMonDirThread(self) - писать больше нечего?
2. TMonDirThread(self).HTTP.Connect; - убери
3. fMonDirMain. lbLog.Items.Add- срочно убери
пока не поймешь что VCL не переваривает "левых" потоков бейся челом об клаву
4.
TMonDirThread(self).HTTP.Disconnect;
if TMonDirThread(self).SSL <> nil then TMonDirThread(self).SSL.Free;
HTTP.Free;
достаточно HTTP.Free;
kaharin (2007-08-31 19:02:00) [4]да...
как выяснилось вся проблема заключается в TIdHTTP
он коряво работает..
то есть спотыкается вот здесь (отправка запроса)
TMonDirThread(self).TInSouse:=TMonDirThread(self).HTTP.Get(TMonDirThread(self).U RLZapros);
и ни туды и ни сюды,
соответственно у меня динамический поток вот и не заканчивается
если ли у кого мысли?
код создания
Function TMonDirThread.prepare_connection():string;
var
tmp_string:string;
begin
case StrToInt(TMonDirThread(self).FK_PROVIDER_ID) of
67..76: begin
TMonDirThread(self).HTTP := TIdHTTP.Create(nil);
TMonDirThread(self).HTTP.Request.UserAgent := 'Mozilla/3.0 (compatible; aviwiever)';
TMonDirThread(self).HTTP.Host:='online.rapida.ru';
TMonDirThread(self).HTTP.Port:=443;
TMonDirThread(self).HTTP.Request.ContentType:='text/xml';
TMonDirThread(self).SSL :=TIdSSLIOHandlerSocket.Create(nil);
TMonDirThread(self).SSL.SSLOptions.CertFile:='C:\sert\rapida\cert.pem';
TMonDirThread(self).SSL.SSLOptions.KeyFile:='C:\sert\rapida\key.pem';
//TMonDirThread(self).SSL.OnGetPassword:= GetKeyPassword;
TMonDirThread(self).SSL.SSLOptions.Method:=sslvSSLv23;
TMonDirThread(self).HTTP.IOHandler:=TMonDirThread(self).SSL;
tmp_string:= '502 041909782;500 '+ TMonDirThread(self).ACCOUNT_NUMBER +';501 '+ TMonDirThread(self).FIO +';503 '+TMonDirThread(self).CONTRACT_NUMBER;
TMonDirThread(self).URLZapros:=www.ru.ru?Params='+tmp_string;
if loging then LogWriteString('Çàïðîñ¹ '+InttoStr(TMonDirThread(self).ThreadID)+'......'+TMonDirThread(self).URLZapros);
end;
end;
Function TMonDirThread.send_pay():string;
begin
case StrToInt(TMonDirThread(self).FK_PROVIDER_ID) of
67..76: begin
try
TMonDirThread(self).prepare_connection;
fMonDirMain.lbLog.Items.Add(TMonDirThread(self).URLZapros);
try
TMonDirThread(self).HTTP.Connect;
TMonDirThread(self).TInSouse:=TMonDirThread(self).HTTP.Get(TMonDirThread(self).U RLZapros); // îòñûëàåì è ïîëó÷àåì îòâåò îò ïðîâàéäåðà
if Length(TMonDirThread(self).TInSouse) 0 then // åñëè îòâåò íå ïóñòîé òî ïåðåäà÷à ïðîøëà óñïåøíî è íà÷èíàåì ïðîâåðÿòü òî ÷òî íàì îòâåòåë ïðîâàéäåð
begin
fMonDirMain.lbLog.Items.Add('2......... '+TMonDirThread(self).TInSouse);
end;
// Parse_pay;
result:='complite';
if loging then LogWriteString('Îòâåò¹ '+InttoStr(TMonDirThread(self).ThreadID)+'......'+TMonDirThread(self).TInSouse);
except
on E : Exception do
begin
fMonDirMain.lbLog.Items.Add(E.Message);
result:='check_fatal';
if loging then LogWriteString('Îøèáêà îòâåò๠'+InttoStr(TMonDirThread(self).ThreadID)+'......'+E.Message);
end;
end;
finally
TMonDirThread(self).HTTP.Disconnect;
if TMonDirThread(self).SSL nil then TMonDirThread(self).SSL.Free;
HTTP.Free;
end;
end;
end;
end;
Сергей М. (2007-08-31 12:49:00) [5]
> Это так случайно осталось (уже убрал)
Вот давай-ка ты сначала все свои "случайности" убери-причеши и выложи только имеющий значение и смысл хорошо отформатированный код - потом и разговор будет серъезный.
kaharin (2007-08-31 12:39:00) [6]Slym -->
1. Убрать goto - согласен
7. Для таких как ты придумали with - это дело привычки
4. Потоки ограничивают объектами синхронизации: в данном случае подойдет hSem:=CreateSemaphore(nil,MaxThread,MaxThread,nil);
для ожидания WaitForSingleObject(hSem,);
для освобождения ReleaseSemaphore - а по подробней плиз
Сергей М. -->
> procedure TMonDirThread.Execute;
> var
> HandleChange: THandle; //Handle ñîçäàâàåìîãî îáúåêòà äëÿ
> îæèäàíèÿ ñîáûòèÿ
> begin
>
> Win32Check(HandleChange INVALID_HANDLE_VALUE);
>А это что за безобразие ?!
Это так случайно осталось (уже убрал)
Сергей М. (2007-08-31 08:24:00) [7]
> procedure TMonDirThread.Execute;
> var
> HandleChange: THandle; //Handle ñîçäàâàåìîãî îáúåêòà äëÿ
> îæèäàíèÿ ñîáûòèÿ
> begin
>
> Win32Check(HandleChange INVALID_HANDLE_VALUE);
А это что за безобразие ?!
Slym (2007-08-31 07:18:00) [8]Решение - навести порядок в коде...
1. Убрать goto
2. Убрать прямое использование контролов формы (lbLog,sbMain,Application)
Логи можно PostMessage или через Synchronize
3. TOPUP_Query - тоже с контролами взаимодействует (EnableControls) и его в потоке нежелательно юзать: создавай внутри потока и пользуй
4. Потоки ограничивают объектами синхронизации: в данном случае подойдет hSem:=CreateSemaphore(nil,MaxThread,MaxThread,nil);
для ожидания WaitForSingleObject(hSem,);
для освобождения ReleaseSemaphore
5. и функция с 16 параметрами это нерулез...
можно же поток Suspend сделать присвоить параметры и потом Resume ему сделать
или лучше Калбак функцию в поток передавать if not OnDataNeed(self) then terminate;
поток запросил, если нету терминат
6. создаваемые потоки отправляешь в свободное плавание, даже ссылки не сохраняешь...
это плохо- заведи список потоков
7. Для таких как ты придумали with
with fMonDirMain.TOPUP_Query do
begin
FieldByName
FieldByName
end;
эквивалентен твоему + оптимизация
fMonDirMain.TOPUP_Query.FieldByName
fMonDirMain.TOPUP_Query.FieldByName
Slym (2007-08-31 05:01:00) [9]Пади еще и ado пользуешь... межпоточно гыгы...
Slym (2007-08-31 04:58:00) [10]ЭТО ПОЛНЫЙ ПИСЕЦ... еще и с GOTO! конструктор с 16! параметрами ааа! ущипните миня! с юзанием контролов формы... перерь понятно почему как бы вылетают (перестают работать)
kaharin (2007-08-30 23:46:00) [11]Продолжение от автора
создание и запуск динамических потоков
procedure TMonDirThread.Execute;
var
HandleChange: THandle; //Handle ñîçäàâàåìîãî îáúåêòà äëÿ îæèäàíèÿ ñîáûòèÿ
begin
Win32Check(HandleChange INVALID_HANDLE_VALUE);
try
//-- Öèêë, ïîêà äëÿ ïîòîêà íå áóäåò âûäàíà êîìàíäà Terminate
case StrToInt(TMonDirThread(self).FK_PROVIDER_ID) of
67..76: begin // Ðàïèäà (áàíêè)
if send_pay = 'complite' then // процедура отправки данных
begin // complite, ïîëó÷èëè îòâåò îò ïðîâàéäåðà (âñå îê)
case StrTOInt(TMonDirThread(self).Error) of
0: begin // ïëàòåæ ïðîøîë áåç îøèáîê
if TMonDirThread(self).Final_status = '1' then // îòâåò îäíîçíà÷íûé çàïèñûâàåì òðàíçàêöèþ
begin
TMonDirThread(self).FK_TOPUP_REQUEST_CODE:='102';
end
else
begin // íóæíî ïåðåïðîâåðÿòü ñòàòóñ, òðàíçàêöèþ íå çàïèñûâàåì è ñòàâèì ñòàòóñ 106 (ïåðåïðîâåðèòü)
// òàêæå çàíîñèì îñíîâíûå ïåðåìåííûå â òàáëèöó PEYMENT (DESCRIPTION)
TMonDirThread(self).FK_TOPUP_REQUEST_CODE:='106';
end;
end;
end;
end
else
begin // ïðîèçîøëà îøèáêà ñâÿçè c ïðîâàéäåðîì
//fMonDirMain.lbLog.Items.Add(' îøèáêà ááìåíà äàííûìè ');
end;
end;
end;
finally
Synchronize(ThreadStop);
// TMonDirThread(self).Terminate;
// TMonDirThread(self).ThreadStop; //Ñîîáùàåì î çàâåðøåíèè ïîòîêà
//Application.ProcessMessages;
end;
end;