Lazarus

Free Pascal => FPC development => Topic started by: BIANCO on February 12, 2018, 02:08:44 am

Title: "exception class 'External :?'."
Post by: BIANCO on February 12, 2018, 02:08:44 am
I am having this problem while destroying a thread.

Project TesteCromis raised exception class 'External :?'.

Does anyone know how to solve it?
-----
I'm using a very cool cron lib from Iztok Kacin, which creates a thread for each task, I need to insert the tasks and destroy them in runtime but this error is happening.

Debugging I got to this point from the Cromis.Scheduler lib, line 1087
class TScheduledEvent

     {$ IFDEF FPC} RTLEventDestroy {$ ELSE} CloseHandle {$ ENDIF} (@ FTermEvent);
The error appears when you pass this line.

"exception class 'External :?'."

The test application is on google drive, please if there was any genius that can help me I appreciate it.

https://drive.google.com/file/d/1w4cIlvFW21uXEeOuiGO3JxSyGm13Lq8w/view?usp=sharing

* This code was initially for Delphi, but works on free Pascal except for this point.

From what I've researched, this is apparently a stdcal or cdecl problem, but I do not know where to change it.
Title: Re: "exception class 'External :?'."
Post by: rvk on February 12, 2018, 09:32:34 am
I can't speak about the problem in Cromos... but I do see a very big problem with you calling Form1 elements within the threads without using Synchronize.

Not only in LoadCronTab and DisplayCronInfo of the main thread but also in the DoOnScheduleStop etc of the cron threads.

One rule... NEVER update a component from another form/thread in a thread without using TThread.Synchronize() or TThread.Queue() !!!

(Maybe that's also the problem with this code in the library but I'm not sure. First fix that.)
Try to take out all the Form1 updates and see if it works then without error.
Title: Re: "exception class 'External :?'."
Post by: BIANCO on February 12, 2018, 02:20:58 pm
Hi, rvk, thanks!

I made the fixes, first on the Main Thread to refresh the screen, but the error continued.

By checking the Threads of the Cromis lib, I have seen that it uses Synchronize () or Queue () depending on the value passed in "SignalType" to execute OnScheduleEvent.

To validate what you have suggested, I have commented the assignment of all the events [were just logs, but updated the screen, ok] minus the OnScheduleEvent that runs in Synchronize ().

Even so, the error continues.

Once again, thank you! but if you have more tips just talk.

If it helps I'm sending the debug screen.
Title: Re: "exception class 'External :?'."
Post by: engkin on February 12, 2018, 03:19:02 pm
In your code you have:
Code: Pascal  [Select][+][-]
  1. procedure TForm1.Button3Click(Sender: TObject);
  2. begin
  3.   ThreadTeste                 := TTheThread.Create(True);
  4.   ThreadTeste.FreeOnTerminate := True;
  5.   ThreadTeste.Start;
  6. end;

If you set FreeOnTerminate := True then you should not touch the thread after starting it. Because the thread will free and destroy itself when it is done.

Button4Click is touching the thread.

More over:
Code: Pascal  [Select][+][-]
  1. procedure TTheThread.Execute;
  2. begin
  3.   try
  4.   repeat
  5.     LoadCronTab;
  6.     DisplayCronInfo;
  7.     Sleep(5000);
  8.   until Terminated;
  9.   finally
  10.     OnTerminate(self);
  11.   end;
  12.  
  13. end;
OnTerminate is usually called if assigned. You are double calling it here. AND you are not checking if it is assigned. (It is *not* assigned).

The logic that calls Execute (when you call start) calls OnTerminate if it is assigned. So you do not have to call it.
Title: Re: "exception class 'External :?'."
Post by: engkin on February 12, 2018, 03:23:11 pm
Code: Pascal  [Select][+][-]
  1. destructor TTheThread.Destroy;
  2. begin
  3.   if Assigned(FScheduleTaskList) then
  4.      FreeAndNil(FScheduleTaskList);
  5.  
  6.   if Assigned(FKnowTasks) then
  7.     FreeAndNil(FKnowTasks);
  8.  
  9.   Self.Terminate;
  10.   inherited Destroy;
  11. end;

That does not make sense. Destroy is called after the terminate ( or Terminated := True )
Title: Re: "exception class 'External :?'."
Post by: rvk on February 12, 2018, 03:29:37 pm
That does not make sense. Destroy is called after the terminate ( or Terminated := True )
Yep, these are all problems in unPrincipal.pas.

But I also see a big problem in Cromis.Scheduler.pas itself (and that's the one causing the RTLEvent call problem).
For instance, there is this in TScheduledEvent.Stop:
Code: Pascal  [Select][+][-]
  1. {$IFDEF FPC}RTLEventSetEvent{$ELSE}SetEvent{$ENDIF}(@FTermEvent);
Ok, so for FPC the RTLEvents are used.
But in TScheduledEvent.Run() there is this:
Code: Pascal  [Select][+][-]
  1. FTermEvent := {$IFDEF MSWINDOWS}CreateEvent(nil, False, False, nil){$ELSE} RTLEventCreate{$ENDIF};
Here, RTLEventCreate() is NOT used because FPC on Windows also has MSWINDOWS defined.

There are a lot of these inconsistencies in the Cromis.Scheduler.pas.
All the IFDEFs for WINDOWS, MSWINDOWS and FPC should be examined and fixed.

BIANCO, where did you get the source-code from?


Edit:
Here is another:
Code: Pascal  [Select][+][-]
  1. {$IFDEF MSWINDOWS}
  2.   Windows, Messages,Types,
  3. {$ELSE}
  4.   LMessages, LCLType, LCLIntf,
  5. {$ENDIF}
Why wouldn't this be defined as:
Code: Pascal  [Select][+][-]
  1. {$IFNDEF FPC}
  2.   Windows, Messages,Types,
  3. {$ELSE}
  4.   LMessages, LCLType, LCLIntf,
  5. {$ENDIF}
Title: Re: "exception class 'External :?'."
Post by: engkin on February 12, 2018, 03:34:06 pm
@rvk: I have two posts above. You saw the second post. The immediate problem is in TTheThread.Execute where he calls OnTerminate without assigning anything to it.
Title: Re: "exception class 'External :?'."
Post by: rvk on February 12, 2018, 03:37:16 pm
The immediate problem is in TTheThread.Execute where he calls OnTerminate without assigning anything to it.
I deleted the call to OnTerminate(self) in TTheThread.Execute but for me the code still crashed in TScheduledEvent.Stop;.

Does the code run correctly for you (clicking Start and Stop)?

B.T.W. the problem code you point to isn't even called because the problem already presents itself before TTheThread is ended.
Title: Re: "exception class 'External :?'."
Post by: engkin on February 12, 2018, 03:56:07 pm
I did not try to compile it. But after reading your post I did the few obvious changes including changing "Stop Thread" and a quick test seemed to run. Waited a few seconds after hitting "Start Thread" then "Stop Thread" waited more. Closed the app. No crash.

That does not mean the app is ok.
Title: Re: "exception class 'External :?'."
Post by: rvk on February 12, 2018, 04:00:18 pm
I did not try to compile it. But after reading your post I did the few obvious changes including changing "Stop Thread" and a quick test seemed to run. Waited a few seconds after hitting "Start Thread" then "Stop Thread" waited more. Closed the app. No crash.
Ok, for topicstarters information: Are you compiling and running on Windows of Linux?

(I still find it strange that all those MSWINDOWS/FPC IFDEFs are really mixed up in Cromis.Scheduler.pas)
Title: Re: "exception class 'External :?'."
Post by: engkin on February 12, 2018, 04:05:25 pm
Win32 FPC 3.0.2
I did not look outside unPrincipal. There might be problems in Cromis units as well. Let me check.
Title: Re: "exception class 'External :?'."
Post by: BIANCO on February 12, 2018, 04:24:06 pm
Code: Pascal  [Select][+][-]
  1. destructor TTheThread.Destroy;
  2. begin
  3.   if Assigned(FScheduleTaskList) then
  4.      FreeAndNil(FScheduleTaskList);
  5.  
  6.   if Assigned(FKnowTasks) then
  7.     FreeAndNil(FKnowTasks);
  8.  
  9.   Self.Terminate;
  10.   inherited Destroy;
  11. end;

That does not make sense. Destroy is called after the terminate ( or Terminated := True )

engkin, rvk,

Sorry, so many errors in the example, but I tried several things, I think my example was still polluted.

engkin, I've removed the redundancy of the main Theread destroy but the error persists as rvk said, the problem is in the destruction of the Threads of Cromis lib.

[I'll check the points pointed out by rvk]
Title: Re: "exception class 'External :?'."
Post by: BIANCO on February 12, 2018, 04:29:07 pm
I did not try to compile it. But after reading your post I did the few obvious changes including changing "Stop Thread" and a quick test seemed to run. Waited a few seconds after hitting "Start Thread" then "Stop Thread" waited more. Closed the app. No crash.
Ok, for topicstarters information: Are you compiling and running on Windows of Linux?

(I still find it strange that all those MSWINDOWS/FPC IFDEFs are really mixed up in Cromis.Scheduler.pas)

I use Windows 8.1 Pro - 64bit
Title: Re: "exception class 'External :?'."
Post by: BIANCO on February 12, 2018, 04:56:11 pm
I did not try to compile it. But after reading your post I did the few obvious changes including changing "Stop Thread" and a quick test seemed to run. Waited a few seconds after hitting "Start Thread" then "Stop Thread" waited more. Closed the app. No crash.
Ok, for topicstarters information: Are you compiling and running on Windows of Linux?

(I still find it strange that all those MSWINDOWS/FPC IFDEFs are really mixed up in Cromis.Scheduler.pas)

Yes, I noticed, however, as I said this lib was initially made in Delphi, but it should work on Lazarus / FPC.

In the
Code: Pascal  [Select][+][-]
  1. {$ IFDEF FPC}
and MSWindows and
Code: Pascal  [Select][+][-]
  1. {$ IFDEF MSWINDOWS}
directives, both are true since I'm using Lazarus and Windows, right?

I believe the event is being signaled correctly, so much so that the event is triggered, so this is working, right?

Code: Pascal  [Select][+][-]
  1. {$ IFDEF FPC} RTLEventSetEvent {$ ELSE} SetEvent {$ ENDIF} (@ FTermEvent);

The original source I got with Iztok Kacim, I put it in the project source in the Cromis folder.

I do not have much experience with Lazarus + FPC, I used Delphi, I thought this would be easier.
Title: Re: "exception class 'External :?'."
Post by: rvk on February 12, 2018, 05:02:58 pm
I believe the event is being signaled correctly, so much so that the event is triggered, so this is working, right?

{$ IFDEF FPC} RTLEventSetEvent {$ ELSE} SetEvent {$ ENDIF} (@ FTermEvent);
That line shows that when using FPC (which we are) the RTLEventSetEvent() is used with FTermEvent.

But looking at this:
Code: Pascal  [Select][+][-]
  1.   TCPHandle = {$IFDEF MSWINDOWS}THandle{$ELSE}PRTLEvent{$ENDIF};
and this:
Code: Pascal  [Select][+][-]
  1.     FTermEvent := {$IFDEF MSWINDOWS}CreateEvent(nil, False, False, nil){$ELSE} RTLEventCreate{$ENDIF};
THandle and CreateEvent() is used because MSWINDOWS is also defined in FPC for Windows.

I suspect this code (and the FPC-codes) are added for FPC under Linux. In that case it would all work out.
As it is now, a THandle created by CreateEvent() will be used with the RTLEventCreate() called in .Stop.

So all the {$IFDEF FPC} should be changed to {$IFNDEF MSWINDOWS} so only Windows-calls are used, or some {$IFDEF MSWINDOWS} should be changed to {$IFNDEF FPC}. It depends on the code within.


(I couldn't find Cromis online anymore anywhere)
Title: Re: "exception class 'External :?'."
Post by: rvk on February 12, 2018, 05:08:54 pm
Something like this:
(I changed all IFDEFs for FPC to the MSWINDOWS counterpart so that RTLEvent isn't used anymore.

Code: [Select]
diff --git "a/C:\\Users\\Rik\\Downloads\\cromis original\\testeCromis\\cromis\\Cromis.Scheduler.pas" "b/C:\\Users\\Rik\\Downloads\\testeCromis\\cromis\\Cromis.Scheduler.pas"
index ae75dbc..eb9d403 100644
--- "a/C:\\Users\\Rik\\Downloads\\New folder (2)\\testeCromis\\cromis\\Cromis.Scheduler.pas"
+++ "b/C:\\Users\\Rik\\Downloads\\testeCromis\\cromis\\Cromis.Scheduler.pas"
@@ -1068,9 +1068,9 @@ begin
     FRunning := False;
 
     // set the terminate event, so that the thread can safely exit
-    {$IFDEF FPC}RTLEventSetEvent{$ELSE}SetEvent{$ENDIF}(@FTermEvent);
+    {$IFNDEF MSWINDOWS}RTLEventSetEvent{$ELSE}SetEvent{$ENDIF}(FTermEvent);
 
-    {$IFNDEF FPC}
+    {$IFDEF MSWINDOWS}
       // wait and block until the scheduling thread is finished
       AResult := WaitForSingleObject(FSchThread.Handle, cShutdownTimeout);
 
@@ -1084,7 +1084,7 @@ begin
     {$ENDIF}
 
     // close the event handle and free the thread
-    {$IFDEF FPC}RTLEventDestroy{$ELSE}CloseHandle{$ENDIF}(@FTermEvent);
+    {$IFNDEF MSWINDOWS}RTLEventDestroy{$ELSE}CloseHandle{$ENDIF}(FTermEvent);
     FreeAndNil(FSchThread);
 
     // fire the on schedule stop event

But there are still some problems in your own code.
For example if you exit your program you first need to end your ThreadTeste thread and wait for it to finish.
Also, there could then still be calls to Form1 but that one is already up by then so they shouldn't execute if Form1 is already freed.
Title: Re: "exception class 'External :?'."
Post by: BIANCO on February 12, 2018, 05:19:57 pm
Yes, it had a public repository, but it's off the air, the lib is larger, I've just added example to the units I use, the original contains parts of a commercial project, I'm waiting for its response to publish in a git original and put here, to see what we can do to make this lib compilable in fpc on windows and linux then.

This is interesting that uses the cron mechanism similar to linux, I have not seen another equal in Pascal or Delphi.
Title: Re: "exception class 'External :?'."
Post by: rvk on February 12, 2018, 05:22:38 pm
Here are two patch files with changes which worked for me (attached).

You see I free the ThreadTeste in FormClose (which means a 5 second delay before the thread responds before closing).
The ThreadTeste.Free is done in FormClose so you need to set FreeOnTerminate to false.

As code:
Code: [Select]
--- testeCromis.org/cromis/Cromis.Scheduler.pas zo feb 11 01:56:48 2018
+++ testeCromis/cromis/Cromis.Scheduler.pas ma feb 12 17:15:50 2018
@@ -1071 +1071 @@ begin
-    {$IFDEF FPC}RTLEventSetEvent{$ELSE}SetEvent{$ENDIF}(@FTermEvent);
+    {$IFNDEF MSWINDOWS}RTLEventSetEvent(@FTermEvent){$ELSE}SetEvent(FTermEvent){$ENDIF};
@@ -1073 +1073 @@ begin
-    {$IFNDEF FPC}
+    {$IFDEF MSWINDOWS}
@@ -1087 +1087 @@ begin
-    {$IFDEF FPC}RTLEventDestroy{$ELSE}CloseHandle{$ENDIF}(@FTermEvent);
+    {$IFNDEF MSWINDOWS}RTLEventDestroy(@FTermEvent){$ELSE}CloseHandle(FTermEvent){$ENDIF};

Code: [Select]
--- testeCromis.org/unprincipal.pas zo feb 11 13:06:35 2018
+++ testeCromis/unprincipal.pas ma feb 12 17:23:45 2018
@@ -71,0 +72 @@ end;
+    procedure FormClose(Sender: TObject; var CloseAction: TCloseAction);
@@ -164 +165 @@ begin
-  ThreadTeste.FreeOnTerminate := True;
+  ThreadTeste.FreeOnTerminate := false;
@@ -173,0 +175,10 @@ end;
+procedure TForm1.FormClose(Sender: TObject; var CloseAction: TCloseAction);
+begin
+  if Assigned(ThreadTeste) then
+  begin
+    ThreadTeste.Terminate;
+    ThreadTeste.WaitFor;
+    ThreadTeste.Free;
+  end;
+end;
+
@@ -208 +219 @@ begin
-  Self.Terminate;
+  //Self.Terminate;
@@ -214 +225 @@ begin
-  try
+  //try
@@ -216,2 +227,2 @@ begin
-    LoadCronTab;
-    DisplayCronInfo;
+    Synchronize(@LoadCronTab);
+    Synchronize(@DisplayCronInfo);
@@ -220,3 +231,3 @@ begin
-  finally
-    OnTerminate(self);
-  end;
+  //finally
+  //  OnTerminate(self);
+  //end;
Title: Re: "exception class 'External :?'."
Post by: runner on February 12, 2018, 06:05:41 pm
Hello people.

I am the original author of the Cromis library. The CRON scheduler is a part of it. So if I can help in any way, I will be glad to. Its quite some time since I used Lazarus / FPC for anything serious but still.

First lets clear the IFDEFS issue. They were added quite some time ago as someone asked me for a Linux FPC support. So I added it. I don't think I tested any of it in full extent. Under Delphi and Windows the unit is tested and use in production environment daily.

But looking over the IFDEFS at a glance I think they are correct. Basically the idea is to call windows API calls like SetEvent, WaitForSingleObject etc under Windows and Linux conterparts (RTL*) under Linux. So using  {$IFDEF WINDOWS} seems correct to me.

Naturally it would be even better to use TEvent and other now build in cross platform objects that Delphi exposes (and I am sure Lazarus RTL has them), but I don't have time to update the code atm.

Will check the code BIANCO sent me under Delphi and Lazarus to see where the issues are.
Title: Re: "exception class 'External :?'."
Post by: rvk on February 12, 2018, 06:21:15 pm
First lets clear the IFDEFS issue. They were added quite some time ago as someone asked me for a Linux FPC support. So I added it. I don't think I tested any of it in full extent. Under Delphi and Windows the unit is tested and use in production environment daily.

But looking over the IFDEFS at a glance I think they are correct. Basically the idea is to call windows API calls like SetEvent, WaitForSingleObject etc under Windows and Linux conterparts (RTL*) under Linux. So using  {$IFDEF WINDOWS} seems correct to me.
Yes, for Delphi under Windows and FPC under Linux the IFDEFs are fine. But for FPC under Windows it is not. For example, like I already said, the IFDEFs for MSWINDOWS and FPC are mixed (MSWINDOWS is also defined in FPC for Windows). The result is that FTermEvent is a THandle and it is created with CreateEvent (for Windows) but in .Stop there are several calls to RTLEvent because FPC is used in the define. Look for all FPC} in the source. They should NOT be there for FPC under Windows because FTermEvent is already a THandle due to the IFDEF MSWINDOWS.

I've created a patch where all IFDEF FPC is changed to IFNDEF MSWINDOWS (and IFNDEF FPC in IFDEF MSWINDOWS). In that case, for FPC under Windows the Windows-events are used and for FPC under Linux the RTLEvents are used.

Note: Under FPC for Windows both MSWINDOWS and FPC are defined. So use one or the other but don't mix them. If the source should run under Delphi for OSX or LINUX then you've got another problem but I don't think that's a target
Title: Re: "exception class 'External :?'."
Post by: BIANCO on February 12, 2018, 06:33:20 pm
\ O /

Your patches worked for the daughter threads correctly, now it's killing the Threas, meaning the events are not being triggered any more.

I'm just having the error if I try to kill the main Thread, from TForm1, can you attach your whole code?
Title: Re: "exception class 'External :?'."
Post by: runner on February 12, 2018, 06:40:20 pm
First lets clear the IFDEFS issue. They were added quite some time ago as someone asked me for a Linux FPC support. So I added it. I don't think I tested any of it in full extent. Under Delphi and Windows the unit is tested and use in production environment daily.

But looking over the IFDEFS at a glance I think they are correct. Basically the idea is to call windows API calls like SetEvent, WaitForSingleObject etc under Windows and Linux conterparts (RTL*) under Linux. So using  {$IFDEF WINDOWS} seems correct to me.
Yes, for Delphi under Windows and FPC under Linux the IFDEFs are fine. But for FPC under Windows it is not. For example, like I already said, the IFDEFs for MSWINDOWS and FPC are mixed (MSWINDOWS is also defined in FPC for Windows). The result is that FTermEvent is a THandle and it is created with CreateEvent (for Windows) but in .Stop there are several calls to RTLEvent because FPC is used in the define. Look for all FPC} in the source. They should NOT be there for FPC under Windows because FTermEvent is already a THandle due to the IFDEF MSWINDOWS.

I've created a patch where all IFDEF FPC is changed to IFNDEF MSWINDOWS (and IFNDEF FPC in IFDEF MSWINDOWS). In that case, for FPC under Windows the Windows-events are used and for FPC under Linux the RTLEvents are used.

Note: Under FPC for Windows both MSWINDOWS and FPC are defined. So use one or the other but don't mix them. If the source should run under Delphi for OSX or LINUX then you've got another problem but I don't think that's a target

Yes you are correct. I examined the code and there is indeed the problem. The original DEFINES were fine, but I think that I added the schedule stop procedure code later and messed up the defines. The corrected procedure should be (rvk that are basically your changes, I am just posting the full code for clarity):

Code: Pascal  [Select][+][-]
  1. procedure TScheduledEvent.Stop;
  2. {$IFDEF MSWINDOWS}
  3. var
  4.   AResult: Cardinal;
  5. {$ENDIF}
  6. begin
  7.   if FRunning then
  8.   begin
  9.     // dealocate the event handler
  10.     FSchThread.OnTerminate := nil;
  11.     FRunning := False;
  12.  
  13.     // set the terminate event, so that the thread can safely exit
  14.     {$IFNDEF MSWINDOWS}
  15.       RTLEventSetEvent(@FTermEvent)
  16.     {$ELSE}
  17.       SetEvent(FTermEvent)
  18.     {$ENDIF};
  19.  
  20.     {$IFDEF MSWINDOWS}
  21.       // wait and block until the scheduling thread is finished
  22.       AResult := WaitForSingleObject(FSchThread.Handle, cShutdownTimeout);
  23.  
  24.       // check if we timed out
  25.       if AResult = WAIT_TIMEOUT then
  26.         TerminateThread(FSchThread.Handle, 0);
  27.     {$ELSE}
  28.       // wait and block until the scheduling thread is finished
  29.       RTLEventWaitFor(FSchThread, cShutdownTimeout);
  30.       FSchThread.Terminate;
  31.     {$ENDIF}
  32.  
  33.     // close the event handle and free the thread
  34.     {$IFNDEF MSWINDOWS}
  35.       RTLEventDestroy(@FTermEvent);
  36.     {$ELSE}
  37.       CloseHandle(FTermEvent);
  38.     {$ENDIF}
  39.     FreeAndNil(FSchThread);
  40.  
  41.     // fire the on schedule stop event
  42.     if Assigned(FOnScheduleStop) then
  43.       FOnScheduleStop(Self);
  44.   end;
  45. end;
  46.  

Basically it should all be WINDOWS based and not FPC based. As I said the DEFINES were made by request from a third party and I never really tested them under FPC or Linux. With this changes there are no more exceptions and the schedule stops as it should. As for the code being cross platform, I never claimed it is :) If it works fine, but I only maintain the Windows Delphi version of it. I really need to put the code into public versioning system so others can contribute.

Also BIANCO I checked your test example and it has several problems. You call GUI from threads without synchronize as others already stated and that is a no-go. Futhermore you don't really need your "TTheThread" class as scheduler already runs in its own thread and you have definied the callback as thread based. So in this case the schedule creates a new anonymous thread under which the task is then executed. Note that all code inside the callback (event) must also be made threadsafe, so any calls to GUI without sync are a no-go.

Also you need to check how to manage threads as you have several problems there also. Not criticising, just pointing it out, as multithreading is not easy and takes a lot of practise. I am doing it for almost 10 year already (heavy multithreading and multi processing) and still get bitten by it :)

Title: Re: "exception class 'External :?'."
Post by: BIANCO on February 12, 2018, 07:09:32 pm
Thankfully for the remarks, I fully agree, others have already mentioned and made the amendments.

But, I did not check the Thread GUI, I

property ThreadTeste: TTheThread ......

as "main thread".

I will carry this functionality to a Daemon / Service so there will be no GUI, this was created
to validate the features.

Once again, thank you very much, even to all!

especially @runner and @rvk.

@Runner, your lib is great already said by email, it would be nice to come to github. :)
Title: Re: "exception class 'External :?'."
Post by: rvk on February 12, 2018, 10:32:05 pm
I'm just having the error if I try to kill the main Thread, from TForm1, can you attach your whole code?
I already showed you a patch of what I changed. I didn't change anything else.
I didn't even use Synchronize (which you should) but that shouldn't prevent the task from running.

Maybe you can show you code again.

But, I did not check the Thread GUI, I
property ThreadTeste: TTheThread ......
as "main thread".
ThreadTeste is NOT the main thread. The application itself (TApplication and the main form) is the main thread. Any other thread you use is another thread. Accessing components in any thread that are in other threads need to be done via Synchronize or Queue.
Title: Re: "exception class 'External :?'."
Post by: BIANCO on February 12, 2018, 11:49:19 pm
You're right! I expressed myself poorly

--------------

Of course, I'm attaching the final code.

https://drive.google.com/file/d/1MJiFqibY6JvzJdrZtbmI3XnVD-HxRwwb/view?usp=sharing

I think we can end this topic as resolved!

I kept creating a  "ThreadTeste" as property of TForm1 because
is part of the concept that I intend to use, a Thread just to monitor and inform the state of the Threads daughter
to a "console".

I do not know if this architecture is the best or the right one, so I'm going to use it anyway because it helps me
to know exactly what is happening with the program, the logs that I send today to the memo,
will be sent to a socket channel that I will use to monitor the daemon / service.

If you look at the example, it was not necessary to put the OnClose of Form1 to the destruction of ThreadTeste,
I kept the "Stop Thread" button, without errors, without memory leaks!

The auxiliary events,

OnScheduleRun,
OnScheduleStop,
OnScheduleAbort,
OnScheduleInvalid,
OnMaxEventsExecuted

are not triggered inside the Synchronize, do not belong to this time and therefore had no problem in uncommenting.

The current solution already caters me, in the future I will better study the management of this list of tasks including
and deleting items without having to stop the "ThreadTeste", which controls the logs.

I will probably put another method in the Synchronize to re-organize the list before entering the log, but this I will try to do first, its I can not get help from the forum.

I loved it, you were 1000!
TinyPortal © 2005-2018