I don't understand why I'm getting EAccessViolation. This happens when closing my application.
I don't understand why I'm getting EAccessViolation. This happens when closing my application.
I'm basically displaying frames. I'm calling a "Start" method after displaying them.
procedure TfrPicpic.Start;
begin
if Assigned(AnonymousThread) then
AnonymousThread.Terminate;
pnDeviceNotReachable.Visible := false;
pnDeviceNotReachable.Align := alNone;
AnonymousThread := TThread.CreateAnonymousThread(
procedure()
var
isopen: boolean;
begin
while not AnonymousThread.CheckTerminated do
begin
if Assigned(Connection) then
isopen := PortIsOpen(5432, Connection.Server);
AnonymousThread.Synchronize(nil,
procedure()
begin
if not isopen and Assigned(pnPicpicEteinds) then
begin
pnDeviceNotReachable.Align := alClient;
pnDeviceNotReachable.Visible := true;
end
else
begin
pnDeviceNotReachable.Visible := false;
pnDeviceNotReachable.Align := alNone;
end;
end);
sleep(500);
end;
end);
AnonymousThread.Priority := tpLower;
AnonymousThread.FreeOnTerminate := false;
AnonymousThread.Start;
end;
Prior destroying them, I'm calling the "Stop" method :
procedure TfrPicpic.Stop;
begin
if Assigned(AnonymousThread) then
AnonymousThread.Terminate;
end;
destructor TfrPicpic.Destroy;
begin
stop;
inherited;
end;
What's going wrong ?
I'm basically displaying frames. I'm calling a "Start" method after displaying them.
procedure TfrPicpic.Start;
begin
if Assigned(AnonymousThread) then
AnonymousThread.Terminate;
pnDeviceNotReachable.Visible := false;
pnDeviceNotReachable.Align := alNone;
AnonymousThread := TThread.CreateAnonymousThread(
procedure()
var
isopen: boolean;
begin
while not AnonymousThread.CheckTerminated do
begin
if Assigned(Connection) then
isopen := PortIsOpen(5432, Connection.Server);
AnonymousThread.Synchronize(nil,
procedure()
begin
if not isopen and Assigned(pnPicpicEteinds) then
begin
pnDeviceNotReachable.Align := alClient;
pnDeviceNotReachable.Visible := true;
end
else
begin
pnDeviceNotReachable.Visible := false;
pnDeviceNotReachable.Align := alNone;
end;
end);
sleep(500);
end;
end);
AnonymousThread.Priority := tpLower;
AnonymousThread.FreeOnTerminate := false;
AnonymousThread.Start;
end;
Prior destroying them, I'm calling the "Stop" method :
procedure TfrPicpic.Stop;
begin
if Assigned(AnonymousThread) then
AnonymousThread.Terminate;
end;
destructor TfrPicpic.Destroy;
begin
stop;
inherited;
end;
What's going wrong ?
Do some debugging. Get a call stack when the exception is raised.
ReplyDeleteWell it happens at TControl.SetVisible (not in front my computer)
ReplyDeleteYou need to call Thread.WaitFor after calling Thread.Terminate.
ReplyDeleteLars Fosdal or you could just call Free on the thread and have it all happen that way.
ReplyDeleteStéphane Wierzbicki Hard to debug away from your computer. Anyway, the point remains. Before solving a problem, first identify it. In this case the way to do that is through debugging. Get that stack trace, and take it from there.
ReplyDeleteDavid Heffernan I totally agree but it's hard to be in front of it's computer from 7.30am to 8.30pm .... ;). Call stack was limited to 3 entries (from memory) :
ReplyDeleteCheckTerminated
Synchronized
TControl.SetVisible
And I jumped into the ASM view...
Thing was that my theads were still running after the application termination. Adding Thread.WaitFor solved my issue (I don't know why I forgot this as it is not the first time I work with worker thread...)
Thank to all of you
Your code doesn't appear to destroy the thread so it leaks. You can replace Termainte and WaitFor with a single call to Free on the thread. The destructor of TThread calls Terminate and WaitFor.
ReplyDeleteDavid Heffernan yes ! will do so... thank you
ReplyDelete