Форум: "Базы";
Текущий архив: 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.034 c