Форум: "Начинающим";
Текущий архив: 2007.09.30;
Скачать: [xml.tar.bz2];
ВнизThread (проблема завершения 3 потока) Найти похожие ветки
← →
kaharin © (2007-08-30 23:44) [0]Суть проблемы в следующем
есть основной поток (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;
← →
kaharin © (2007-08-30 23:46) [1]Продолжение от автора
создание и запуск динамических потоков
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;
← →
Slym © (2007-08-31 04:58) [2]ЭТО ПОЛНЫЙ ПИСЕЦ... еще и с GOTO! конструктор с 16! параметрами ааа! ущипните миня! с юзанием контролов формы... перерь понятно почему как бы вылетают (перестают работать)
← →
Slym © (2007-08-31 05:01) [3]Пади еще и ado пользуешь... межпоточно гыгы...
← →
Slym © (2007-08-31 07:18) [4]Решение - навести порядок в коде...
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. Для таких как ты придумали withwith fMonDirMain.TOPUP_Query do
begin
FieldByName
FieldByName
end;
эквивалентен твоему + оптимизацияfMonDirMain.TOPUP_Query.FieldByName
fMonDirMain.TOPUP_Query.FieldByName
← →
Сергей М. © (2007-08-31 08:24) [5]
> procedure TMonDirThread.Execute;
> var
> HandleChange: THandle; //Handle ñîçäàâàåìîãî îáúåêòà äëÿ
> îæèäàíèÿ ñîáûòèÿ
> begin
>
> Win32Check(HandleChange <> INVALID_HANDLE_VALUE);
А это что за безобразие ?!
← →
kaharin © (2007-08-31 12:39) [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 12:49) [7]
> Это так случайно осталось (уже убрал)
Вот давай-ка ты сначала все свои "случайности" убери-причеши и выложи только имеющий значение и смысл хорошо отформатированный код - потом и разговор будет серъезный.
← →
kaharin © (2007-08-31 19:02) [8]да...
как выяснилось вся проблема заключается в 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;
← →
Slym © (2007-09-03 14:17) [9]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;
← →
Сергей М. © (2007-09-03 14:28) [10]
> TMonDirThread(self)
Это зачем ?
← →
evvcom © (2007-09-03 14:31) [11]
> для освобождения ReleaseSemaphore - а по подробней плиз
А книжку умную почитать? Или тебе ее сюда выложить?
Про потоки почитай, про синхронизацию, примеры разбери, что бывает, когда нет синхронизации, а потом подумай, а заточена ли VCL под мультипоточность?
Страницы: 1 вся ветка
Форум: "Начинающим";
Текущий архив: 2007.09.30;
Скачать: [xml.tar.bz2];
Память: 0.54 MB
Время: 0.045 c