Hi there,
our company has written an application which has a connection with another application.
This application is a TCP client program that sends TCP commands to our program.
Our program interpretes these commands and generates pulses. When these pulses are generated, an ARCNET network is scanned to see if someone interrupts this pulse. This sequence is done app. every 5 seconds. When the ARCNET message comes in, the application stops generating pulses, sends out some TCP messages to the client program and waits for another command of the client.
The pulses are generated via an hardware card and are given on our application through a DLL who scans the INTERRUPT of this card.
Next to this, there are two threads in our application, one TCP Thread and one ARCNET thread. Next to these there are app. 14 other threads generated by Delphi components who we are using in other projects.
Now to the problem. After a certain time, the application comes into the state 'Not responding'. Windows is still working fine but the application needs to be closed down with Ctrl-Alt-Del. I've inserted logging in the application to see if it the threads aren't blocking each other but everything seems fine. To call a method from within the TCP thread or the ARCNET thread we use the synchronize methods.
When the application hangs, it is the main thread that is hanging. Can anyone help me futher with this problem??
Or can anyone advice me good tools to detect the problem better?? I'm stuck with this problem for several months now and don't see a solution yet, worse, I don't know where to search anymore....
So all help, tips, tools or other things I can use to search this problem are welcome.
Here is the code of the execute methods of the self-made threads :
THE ARCNET THREAD
procedure TAtsArcThread.Execute;
var
bStop: boolean;
msg: S1000Message;
iLen: integer;
hWnd: cardinal;
iError: integer;
lwait: ulong;
i, read, write: integer;
bVerwerkt: boolean;
str: string;
pmsg: pS1000Message;
lSelectResult: integer;
UsersOk: boolean;
begin
bStop := false;
iLen := sizeof(S1000Message);
hWnd := 0;
lWait := 0; // DN 061003 was 500
read := 1;
write := 1;
while (not bStop) do
begin
try
read := 0;
lSelectResult := fArc.select(read, write, lWait);
while read > 0 do
begin
read := read - 1;
iError := farc.receive(msg, iLen);
if (SMCOK = iError) then
begin
farc.a_bARCOk := true;
i := 0;
bVerwerkt := false;
UsersOk := false;
syncmsg := msg;
synchronize(GotoMainThread
);
==>GOING TO MAIN THREAD
end
else
begin
if not (farc.lasterror = SMCRECEIVEFAILED) then
begin
farc.a_bARCOk := false;
end;
end;
end;
read := 1;
write := 1;
// Controleer of thread moet stoppen
bStop := (WAIT_OBJECT_0 = WaitForSingleObject(farc.e
_hStop, 0));
if bStop then
templog(1, 'Arcnet thread gestopt!, (WAIT_OBJECT_0 = WaitForSingleObject(farc.e
_hStop, 0)) = TRUE');
except
on E: Exception do
begin
templog(2, 'Arcnet thread exception : ' + E.Message);
read := 1;
write := 1;
end;
end;
end;
//Zo wordt de thread beter afgesloten
//Geen int 3 breakpoint of memoryleaks meer
//Moet zo ongeveer, duidelijk voorbeeld in de help ontbreekt natuurlijk weer
PostQuitMessage(0);
end;
The GOTOMAINTHREAD METHOD FOR THIS THREAD (frmclockcontroller is the main thread) :
procedure TatsArcThread.GotoMainThre
ad;
var
i: integer;
bVerwerkt: Boolean;
begin
i := 0;
bVerwerkt := false;
while ((not bVerwerkt) and (i < CNSARCNET_MAXUSERS)) do
begin
if not (farc.a_arcUsers[i] = nil) then
begin
if ((S1000Message(Syncmsg).hd
r.cmd = ARCCMD_KOOP) and (frmClockController.ClockE
ngine.Cloc
kStatus = csClockTurningDown)) then
begin
ErIsGekocht := True;
frmClockController.AddExce
ption('«SM
CARC MAINTHREAD» ArcNet bericht KOOP');
end
else
frmClockController.AddExce
ption('«SM
CARC MAINTHREAD» ArcNet bericht ONBEKEND');
bVerwerkt := farc.a_arcUsers[i].ThreadP
roc(Syncms
g);
end;
inc(i);
end;
end;
THE TCP THREAD
procedure TVMT.TCPServerExecute(AThr
ead: TIdPeerThread);
// Hier komt het bericht van de VMT (tcp/ip) binnen
begin
try
TCPConnectionThread := AThread;
ClientIP := AThread.Connection.Socket.
Binding.Pe
erIP;
while AThread.Connection.Connect
ed do
begin
VMTString := AThread.Connection.ReadLn(
'~', 10, -1);
Athread.synchronize(GotoMa
inThread);
==> GOTO THE MAIN THREAD
end;
except
on E: Exception do
templog(2, 'TCPServerExecute Exception : ' + E.Message);
end;
end;
THE GOTOMAINTHREAD EXECUTE METHOD FOR ABOVE THREAD
procedure TVMT.GotoMainThread;
var
i : Integer;
tempstring,temp : string;
begin
{$IFDEF DNVMT}
vmtThread.AddMessage(VMTSt
ring);
{$ELSE}
temp := vmtstring;
tempstring:='';
for i:= 1 to length(temp) do
tempstring:= tempstring + ' '+ inttostr(ord(temp[i]));
frmClockController.AddExce
ption('«VM
T MAINTHREAD» TCP ontvangen ' + tempstring);
TranslateReceivedValue(VMT
String);
==>TRANSLATERECEIVEVALUE IS A METHOD IN THE MAIN THREAD!!!
{$ENDIF}
end;