Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2004.09.12;
Скачать: CL | DM;

Вниз

Как можно убить запущенный поток?   Найти похожие ветки 

 
Rusa   (2004-08-18 07:41) [0]

Имею программу, которая запускает несколько потоков, производящих независимые подключения к базе данных Оракл и вызывающих там хранимую процедуру. Каждый поток передает на вход процедуры свои параметры. В среднем каждая процедура отрабатывает за 10 минут, поэтому я ее запуск выделяю в отдельный поток что-бы интерфейс программы не висел. Все нормально работает и выполняется, есть у меня только вот такой вопрос. Иногда надо бывает завершить работу программы до завершения выполнения хранимых процедур на сервере. Как правильно убить в таком случае мои запущенные потоки? В документации написано, что для того что-бы пользоваться методом TThread.Terminate надо в TThread.Execute постоянно проверять свойство Terminated и далее делать выводы о работе потока. У меня не получиться этого делать, т.к. после вызова метода ExecProc для хранимой процедуры я уже не смогу проверять никакие свойства, вплодь до ее завершения. Есть ли еще какие-нибудь способы в данной ситуации, что-бы убить потоки?

Привожу свой код:

Класс потока

unit thread;

interface

uses
 Classes, DbTables, datamod, Windows, SysUtils, DB;

type
 TOraThread = class( TThread )
 private
 protected
   FDatabase: TDatabase;
   FStoredProc: TStoredProc;
   FSession: TSession;
   procedure Execute; override;
 public
   FTownId: Byte;
   FBillTypeId: Byte;
   constructor Create( aReportDateId: Byte;
                       aReportDateId2: Byte;
                       aSysDate: TDateTime;
                       aBillTypeId: Byte;
                       aTownId: Byte;
                       aTruncateFlag: Byte );
 end;

implementation

{ TOraThread }

procedure TOraThread.Execute;
begin
 if Assigned( FStoredProc ) then
 begin
   FStoredProc.Close;
   if not FStoredProc.Prepared then FStoredProc.Prepare;
   FStoredProc.ExecProc;
   InterlockedDecrement( thread_count );
   FStoredProc.Close;
   FStoredProc.Free;
   FStoredProc := nil;
 end;
 if Assigned( FDatabase ) then
 begin
   FDatabase.Connected := False;
   FDatabase.Free;
   FDatabase := nil;
 end;
 if Assigned( FSession ) then
 begin
   FSession.Active := False;
   FSession.Free;
   FSession := nil;
 end;
end;

constructor TOraThread.Create( aReportDateId: Byte;
                              aReportDateId2: Byte;
                              aSysDate: TDateTime;
                              aBillTypeId: Byte;
                              aTownId: Byte;
                              aTruncateFlag: Byte );
begin
 inherited Create( True );
 FTownId := aTownId;
 FBillTypeId := aBillTypeId;
 FSession := TSession.Create( dm );
 with FSession do
 begin
   Active := False;
   Name := "Session" + IntToStr( thread_count );
   KeepConnections := False;
   SessionName := "Session" + IntToStr( thread_count );
 end;
 FDatabase := TDatabase.Create( dm );
 with FDatabase do
 begin
   Connected := False;
   DatabaseName := "DatabaseName" + IntToStr( thread_count );
   Name := "DatabaseName" + IntToStr( thread_count );
   SessionName := "Session" + IntToStr( thread_count );
   KeepConnection := False;
   LoginPrompt := False;
   AliasName := dm.Database.AliasName;
   Params.Clear;
   Params.Add( "user name" );
   Params.Values[ "user name" ] := username;
   Params.Add( password );
   Params.Values[ "password" ] := password;
 end;
 FStoredProc := TStoredProc.Create( dm );
 with FStoredProc do
 begin
   Active := False;
   DatabaseName := "DatabaseName" + IntToStr( thread_count );
   Name := "StoredProc" + IntToStr( thread_count );
   StoredProcName := "XXX.XXXXXXXXXXXXX";
   SessionName := "Session" + IntToStr( thread_count );
   Params.Clear;
   Params.CreateParam( ftSmallInt, "p_report_date_id", ptInput );
   Params.CreateParam( ftSmallInt, "p_report_date_id2", ptInput );
   Params.CreateParam( ftDate, "p_sys_date", ptInput );
   Params.CreateParam( ftSmallInt, "p_bill_type_id", ptInput );
   Params.CreateParam( ftSmallInt, "p_town_id", ptInput );
   Params.CreateParam( ftSmallInt, "p_trc", ptInput );
   ParamByName( "p_report_date_id" ).AsSmallInt := aReportDateId;
   ParamByName( "p_report_date_id2" ).AsSmallInt := aReportDateId2;
   ParamByName( "p_sys_date" ).AsDate := aSysDate;
   ParamByName( "p_bill_type_id" ).AsSmallInt := aBillTypeId;
   ParamByName( "p_town_id" ).AsSmallInt := aTownId;
   ParamByName( "p_trc" ).AsSmallInt := aTruncateFlag;
 end;
 FDatabase.Connected := True;
end;

end.

Вызовы из основного модуля:

 if KeepWorking = False then exit;
 InterlockedIncrement( thread_count );
 aThread := TOraThread.Create( report_date_id,
                               report_date_id2,
                               sys_date,
                               bill_type_id,
                               town_id,
                               trc );
 ThreadList.Add( aThread );
 aThread.Priority := tpNormal;
 aThread.FreeOnTerminate := True;
 aThread.OnTerminate := OnThreadFinished;
 StatusBar1.SimpleText := "Started ...";
 aThread.Resume;
 while (( thread_count <> 0 ) and
        ( thread_count >= StrToInt( fmOptions.meMaxThreadCount.Text ))) do
 begin
   Application.ProcessMessages;
   Sleep( 350 );
 end;

procedure TFormMain.OnThreadFinished( Sender: TObject );
var i: Byte;
begin
 Memo.Lines.Add( "Thread finished." );
 ThreadList.Remove( aThread );
end;

// Вот как я делаю принудительное закрытие на данный момент
// Terminate не дает нужного результата. Приходиться ждать
// завершения уже запущенных потоков
procedure TFormMain.tbExitClick(Sender: TObject);
begin
 Memo.Lines.Add( "Принудительное завершение" );
 KeepWorking := False;
 PostQuitMessage( 0 );
 aThread := nil;
 if Assigned( ThreadList ) then
 begin
   while ( ThreadList.Count > 0 ) do
   begin
     aThread := ThreadList.Last;
     aThread.WaitFor;
     if ( ThreadList.IndexOf( aThread ) <> -1 ) then ThreadList.Remove( aThread );
     aThread := nil;
   end;
 end;
 Close;
end;

P.S. Спасибо всем кто смог дочитать до конца мой вопрос :))


 
Evgeny V ©   (2004-08-18 08:56) [1]

TerminateThread, но не желательно без крайней необходимости.



Страницы: 1 вся ветка

Текущий архив: 2004.09.12;
Скачать: CL | DM;

Наверх




Память: 0.48 MB
Время: 0.03 c
4-1091101641
ilop
2004-07-29 15:47
2004.09.12
Как закрыть системный процесс типа process.exe


14-1093356079
Александр1
2004-08-24 18:01
2004.09.12
Star force


9-1085025564
маг Гыр
2004-05-20 07:59
2004.09.12
Фон в игре


3-1092339929
Сергей Плоткин
2004-08-12 23:45
2004.09.12
Огромный размер БД


6-1089053117
leonidus
2004-07-05 22:45
2004.09.12
TidHTTP при работе в потоке