fnaaijkens
Member
Although knowledgeable about Delphi and theoretically aware of aspects of multi-threaded programming I seem unable to create a QueryThread in Delphi, that is monitored (in time) by a second thread, calling the query to end and the querythread to terminate if the SQL takes to much time.
Sounds simple enough, but the best I can do is programmed death by calling to terminate the other Thread (wrongly) so the app generates an access violation error, which *does* relieve the server but is the worst nightmare from a programmers point of view
I have a WebModule Action that is called, that is to create the monitoring thread, and subsecquently, the query-thread. The query can run for, say, 20 seconds,
and I want to kill it in mid-air, say 10 seconds. Maybe the logon is too slow, or the query too heavy.
I'm assuming you don't need the unit and form the main module uses. I'll probably making enough mistakes in this module.
The code goes like this:
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
unit wn_main;
interface
uses
Windows, Messages, SysUtils, Classes, HTTPApp, Oracle, ExtCtrls;
type
TOracleThreadParamType = record
Header: string;
Field: string;
AHref: string;
end;
TOracleMonitorThread = class(TThread)
private
MaxTime : longword;
StopWatchCount : longword;
protected
MayBeKilled : boolean;
procedure Execute; override;
procedure KillMonitorThread;
procedure KillQueryThread;
end;
TOracleRetrieveThread = class(TThread)
private
Sessie : TOracleSession;
QueryParams : array of TOracleThreadParamType;
Query : TOracleQuery;
StopWatchCount : longword;
QueryHasPerformed : boolean;
protected
procedure OnTerminate;
procedure Execute; override;
procedure Start(
ASession: TOracleSession; AQuery: TOracleQuery; var TheParams: array of TOracleThreadParamType
);
function AddElementFromQuery(OracleQueryField: string): string;
public
MASTER_RESULT : string;
end;
TWM_Nains = class(TWebModule)
ORA_Session: TOracleSession;
ORA_Retrieve_Locations: TOracleQuery;
ORA_Retrieve_NetworkElements: TOracleQuery;
ORA_Retrieve_Countries_For_Locations: TOracleQuery;
ORA_Retrieve_Countries_Old_Way: TOracleQuery;
ORA_Circuits: TOracleQuery;
procedure WA_LongRetrievalAction(Sender: TObject; Request: TWebRequest; Response: TWebResponse; var Handled: Boolean);
procedure WebModuleCreate(Sender: TObject);
procedure WebModuleDestroy(Sender: TObject);
private
public
MonitorThread : TOracleMonitorThread;
QueryThread : TOracleRetrieveThread;
end;
const
LimitedUserQuery: boolean = true;
LimitedUserNumber : integer = 255;
SYSTEM_TERMINATED : boolean = false;
footer = 'bismillah'
var
WM_Nains: TWM_Nains;
implementation
uses
ecodelfi
;
{$R *.DFM}
function __citystr(s: string): string;
var i: integer;
begin
i := pos('-', s);
if i = 0 then Result := s else Result := copy(s, 1, i-1);
end;
// Generic function to replace word of sentence in other sentence, allowing to force entire word or phrase.
// Will not change original
function ReplaceOccurrences(source, findst, replacest: string; EntireWordOnly: boolean): string;
var i, lasti: longint; src : string;
begin
i := 0; src := source;
repeat
lasti := i;
i := pos(findst, src);
if (
(i > 0) and ( // zowieso iets gevonden
not EntireWordOnly or (
((i=1) or (src[i-1] = ' ')) and // of eerste woord of spatie ervoor
(((i + length(findst) - 1) = length(src)) or (src[i+length(findst)] = ' '))
)
)
) then begin // of laatste woord of spatie erachter (zeker als punten al spaties zijn geworden
system.delete(src, i, length(findst)); // dan mag ik findst weggooien
system.insert(replacest, src, i); // en er replacest voor in de plaats inserten.
end; //if i > 0 then __logapp(findst + ' ::= ' + replacest + ' in ' + source);
until (i = 0) or (lasti = i);
Result := src;
end;
procedure TWM_Nains.WebModuleCreate(Sender: TObject);
begin
__SetPurge(7); logfilename := __progdir + 'naiswb.log'; programname := 'NAINSWB'; __loginit;
logheader[05] := '
Sounds simple enough, but the best I can do is programmed death by calling to terminate the other Thread (wrongly) so the app generates an access violation error, which *does* relieve the server but is the worst nightmare from a programmers point of view

I have a WebModule Action that is called, that is to create the monitoring thread, and subsecquently, the query-thread. The query can run for, say, 20 seconds,
and I want to kill it in mid-air, say 10 seconds. Maybe the logon is too slow, or the query too heavy.
I'm assuming you don't need the unit and form the main module uses. I'll probably making enough mistakes in this module.
The code goes like this:
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
unit wn_main;
interface
uses
Windows, Messages, SysUtils, Classes, HTTPApp, Oracle, ExtCtrls;
type
TOracleThreadParamType = record
Header: string;
Field: string;
AHref: string;
end;
TOracleMonitorThread = class(TThread)
private
MaxTime : longword;
StopWatchCount : longword;
protected
MayBeKilled : boolean;
procedure Execute; override;
procedure KillMonitorThread;
procedure KillQueryThread;
end;
TOracleRetrieveThread = class(TThread)
private
Sessie : TOracleSession;
QueryParams : array of TOracleThreadParamType;
Query : TOracleQuery;
StopWatchCount : longword;
QueryHasPerformed : boolean;
protected
procedure OnTerminate;
procedure Execute; override;
procedure Start(
ASession: TOracleSession; AQuery: TOracleQuery; var TheParams: array of TOracleThreadParamType
);
function AddElementFromQuery(OracleQueryField: string): string;
public
MASTER_RESULT : string;
end;
TWM_Nains = class(TWebModule)
ORA_Session: TOracleSession;
ORA_Retrieve_Locations: TOracleQuery;
ORA_Retrieve_NetworkElements: TOracleQuery;
ORA_Retrieve_Countries_For_Locations: TOracleQuery;
ORA_Retrieve_Countries_Old_Way: TOracleQuery;
ORA_Circuits: TOracleQuery;
procedure WA_LongRetrievalAction(Sender: TObject; Request: TWebRequest; Response: TWebResponse; var Handled: Boolean);
procedure WebModuleCreate(Sender: TObject);
procedure WebModuleDestroy(Sender: TObject);
private
public
MonitorThread : TOracleMonitorThread;
QueryThread : TOracleRetrieveThread;
end;
const
LimitedUserQuery: boolean = true;
LimitedUserNumber : integer = 255;
SYSTEM_TERMINATED : boolean = false;
footer = 'bismillah'
var
WM_Nains: TWM_Nains;
implementation
uses
ecodelfi
;
{$R *.DFM}
function __citystr(s: string): string;
var i: integer;
begin
i := pos('-', s);
if i = 0 then Result := s else Result := copy(s, 1, i-1);
end;
// Generic function to replace word of sentence in other sentence, allowing to force entire word or phrase.
// Will not change original
function ReplaceOccurrences(source, findst, replacest: string; EntireWordOnly: boolean): string;
var i, lasti: longint; src : string;
begin
i := 0; src := source;
repeat
lasti := i;
i := pos(findst, src);
if (
(i > 0) and ( // zowieso iets gevonden
not EntireWordOnly or (
((i=1) or (src[i-1] = ' ')) and // of eerste woord of spatie ervoor
(((i + length(findst) - 1) = length(src)) or (src[i+length(findst)] = ' '))
)
)
) then begin // of laatste woord of spatie erachter (zeker als punten al spaties zijn geworden
system.delete(src, i, length(findst)); // dan mag ik findst weggooien
system.insert(replacest, src, i); // en er replacest voor in de plaats inserten.
end; //if i > 0 then __logapp(findst + ' ::= ' + replacest + ' in ' + source);
until (i = 0) or (lasti = i);
Result := src;
end;
procedure TWM_Nains.WebModuleCreate(Sender: TObject);
begin
__SetPurge(7); logfilename := __progdir + 'naiswb.log'; programname := 'NAINSWB'; __loginit;
logheader[05] := '