Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

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;


Наверх

Титульная страница Поиск, карта сайта Написать письмо