Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Базы";
Текущий архив: 2004.09.12;
Скачать: [xml.tar.bz2];

Вниз

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

 
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;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.47 MB
Время: 0.045 c
1-1093525524
AlexXn
2004-08-26 17:05
2004.09.12
Тэги HTML


4-1091016954
Катя
2004-07-28 16:15
2004.09.12
Снять с файла атрибут


4-1090596820
parovoZZ
2004-07-23 19:33
2004.09.12
Картинка в пункте меню


1-1093514540
Garry
2004-08-26 14:02
2004.09.12
Скопировать лист в книге Excel


1-1093518682
mouse_web
2004-08-26 15:11
2004.09.12
Функции string





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский