Search the Community
Showing results for tags 'thread'.
Found 11 results
-
HI. I hope someone can give me a hint here. Printque is a Form created in the Main Thread, just before calling this thread. Its Formcreate contains this line: Tstuckthread.Create(Tprintqueue(self),printernames); The problem is in the showform procedure at the line .A.show It gives no error, but the app becomes unresponsive. The main form is hidden, and I have to stop the app.I Tstuckthread= class(TThread) private FForm: TFORM; L:tSTRINGLIST; function STUCK(title:string;l:Tstringlist): boolean; procedure listjobs(allprinters: string); protected public constructor Create(ownerForm:TFORM;printernames:string; ARUNS: INTEGER=0); destructor Destroy; override; procedure Execute(); override; procedure showform; published end; constructor Tstuckthread.Create(ownerForm: TFORM;printernames: string;ARUNS: INTEGER=0); begin L:=tSTRINGLIST.CREATE; FForm:= ownerForm; Self.FreeOnTerminate := True; inherited Create; end; destructor Tstuckthread.Destroy; begin inherited; L.FREE; end; procedure Tstuckthread.Execute; begin done :=FALSE; while not Terminated AND NOT done do begin <get printjobs list and save it in L......> if L.count>0 then BEGIN /// fine HERE Tprintqueue(FForm).MEMO1.LINES.ASSIGN(L); // fine HERE Synchronize(SHOWForm); SLEEP(500); END; DONE:=TRUE; end; end; And here is the showform() procedure; procedure Tstuckthread.showform; VAR A: Tprintqueue; begin A:=Tprintqueue(FForm); TRY IF NOT A.VISIBLE THEN A.show; // PROBLEM HERE. EXCEPT a.free;// 4 testing. It never gets there. END;
-
Hi everybody. I hope somebody could help me with this "leaks" report from FastMM4.. I have no idea what BaseThreadInitThunk and similar mean.. --------------------------------2024/6/27 17:52:48-------------------------------- A memory block has been leaked. The size is: 20 This block was allocated by thread 0x38E4, and the stack trace (return addresses) at the time was: C775C2 [System.pas][System][@GetMem$qqri][4962] C7C6F8 [System.pas][System][@StartExe$qqrp23System.PackageInfoTablep17System.TLibModule][24306] 75F2FCC9 [BaseThreadInitThunk] 77AD7CBE [RtlGetAppContainerNamedObjectPath] 77AD7C8E [RtlGetAppContainerNamedObjectPath] The block is currently used for an object of class: IdThreadSafe.TIdThreadSafeInteger The allocation number is: 7395 --------------------------------2024/6/27 17:52:48-------------------------------- A memory block has been leaked. The size is: 36 This block was allocated by thread 0x38E4, and the stack trace (return addresses) at the time was: C775C2 [System.pas][System][@GetMem$qqri][4962] 18F665B C7C6F8 [System.pas][System][@StartExe$qqrp23System.PackageInfoTablep17System.TLibModule][24306] 75F2FCC9 [BaseThreadInitThunk] 77AD7CBE [RtlGetAppContainerNamedObjectPath] 77AD7C8E [RtlGetAppContainerNamedObjectPath] The block is currently used for an object of class: IdGlobal.TIdCriticalSection The allocation number is: 6886. This is my coce; TTCPEchoDaemon = class(TThread) private Sock:TTCPBlockSocket; public Constructor Create; Destructor Destroy; override; procedure Execute; override; end; Constructor TTCPEchoDaemon.Create; begin inherited create(true); if self.Handle = 0 then raise EThread.CreateResFmt(@SThreadCreateError, ['ECHO Daemon '+SysErrorMessage(GetLastError)]); FreeOnTerminate:=true; resume; sock:=TTCPBlockSocket.create; end; procedure TTCPEchoDaemon.Execute; var ClientSock:TSocket; begin with sock do begin CreateSocket; setLinger(true,10000); bind(SERVERIP,portnumber); listen; repeat if terminated or _stopdeamon then break; if canread(1000) then begin // *** there is code here, but for this test it // *** never gets execute b/c nothing is sent. end; until false; end; end; Destructor TTCPEchoDaemon.Destroy; begin Sock.free; inherited destroy; end;
-
Can ICS thread cause memory violation? (EOutOfResources error)
PizzaProgram posted a topic in ICS - Internet Component Suite
I have a huge app (pizzaprogram) running for 20+ years rock stable on hundreds of PCs, written in Delphi7, using: AlphaSkin + Indy + UIB + TVirtualStringTree also had 5 background threads running without any problems. (Some of them are using UIB.) This year I've started to work with `OverbyteIcsSslHttpRest, OverbyteIcsLogger, OverbyteIcsSslJose, OverbyteIcsSslX509Utils, OverbyteIcsWSocket, OverbyteIcsSuperObject, OverbyteIcsHttpProt, OverbyteIcsUtils, OverbyteIcsSSLEAY` units, running in a 6th separated thread. Since then, every 1-6 hours my program is crashing with EOutOfResources whenever AlphaSkin is trying to create or resize a bigger Bitmap. I've upgraded AlphaSkin from 2019 version to latest, but it did not help. (Actually it made it even worth, because the new version is generating 32bit bitmaps for every form and panel and button forehead.) The private memory consumption of my EXE is always under <150MB , usually 75MB Peak Virtual memory size < 300MB GDI number < 900 Please give me some hint / advice, how could I solve this mystery?- 76 replies
-
- thread
- eoutofresources
-
(and 2 more)
Tagged with:
-
Hi everybody, I'm using Delphi 12 on Windows for Desktop applications. I've an FMX project done in single threaded mode (classical without threads) with timers and I have a problem with animation of objects inside frames! The project is structured like that : A main form with 2 timers and 3 layouts (Top, Main, Bottom). 1 - The first timer is in charge to display successively TFrames regarding a process inside the layouts 2 - The second one is in charge of the standby mode management A second form with 5 timers in charge of the communication with a PLC 1 - The 5 timers have different frequencies in order to read different values of the PLC (500 ms, 1s, 1.5s, etc) In the main form, on specifics frames, I've some objects (like TArc or TRectangle, etc.) that are animated by using TFloatAnimation. My problem is that these animations are lagging. Trying to analyse the problem I made a try without timers and it seems to work smoothly but it is hard to conclude if it is only the timers! I would like to create some threads to eliminate the timers and my idea is to create one thread by frequency of reading. But when I will call the method to read from the "Execute" function of the thread, the method called will be located inside the second form in a specific class (but the method is not located in a visual component of the FMX library). So my questions are: Should I use "Synchronize" even if the method called is not a visual component ? I'm afraid of the fact that it could slow down the application as before by the timers if each thread is all the time Synchronizing to make the different read methods calls! To replace the 2 timers of the main thread, I imagined the use of 2 more threads to send events to the main form to let it know when it is needed to change of frame or going in standby mode. Is there a good idea? Is there really the good approach? I'm a little bit lost never stopping to think to do it in the better way. Many thanks to all in advance for your contributions.
- 3 replies
-
- lag
- multithreading
-
(and 4 more)
Tagged with:
-
HI. I can't understand why Madexcept shows a leak on FIndFirst/FindClose. THis is what I have : type SendThread = class(TThread) private CriticalSection: TCriticalSection; fmods:modslist; tablename: string; savedir: string; dbase: string; uniq: integer; public Constructor Create(afmods:modslist; atablename: string;uniquenumber: int64;asavedir,adbase: string); Destructor Destroy; override; procedure Execute; override; procedure Fields2sTREAM(fmods:modslist; tablename: string; dbase: Tnxdatabase); end; CriticalSection is created in the Create constructor and free-d in Destroy. In the Execute, I have this. CriticalSection.Acquire; try s:=savedir+'\*'+lowercase(dm2.uniquenumber.tablename)+'.db'; if findfirst(s,faAnyFile,sr)=0 then begin Deletefile(savedir+'\'+sr.name); FindClose(SR); end; s:=Format('%.*d',[13, uniq]); s:= savedir+'\'+s+'$pos-'+lowercase(dm2.uniquenumber.tablename)+'.db'; sStream.savetofile(s); finally CriticalSection.Release; end; Any clue anybody?
-
HI In the following code I put 2 breakpoints at the beginning of Thread.Create and of Thread.Destroy. I noticed that in all cases except one the sequence Crate/Destroy is executed in the correct order. But in one case, Destroy is called twice in a row. Does anybody have an idea as to why? Constructor SendThread.Create(afmods:modslist; atablename: string;uniquenumber: int64;asavedir,adbase: string); begin inherited create(false); FreeOnTerminate:=true; fmods:=afmods; tablename:=atablename; uniq:=uniquenumber; dbase:=adbase; savedir:=asavedir; sstream:=TStringstream.create; end; Destructor SendThread.Destroy; begin sstream.free; inherited Destroy; end; procedure SendThread.Execute; var s,last1: string; l,i,n,modindex: integer; done: boolean; t: textfile; begin if length(fmods)<=0 then exit; modindex:=getmodindex(inttostr(uniq),fmods); with fmods[modindex] do begin // s:=format('%-11s',[fmods[high(fmods)].val]); // sStream.writestring(s); for l:=0 to high(mods) do begin sstream.writestring(format('%4s',[inttostr(mods[l].fieldpos)])); sstream.writestring(format('%10d',[length(mods[l].val)])); sStream.writestring(mods[l].val); END; mods:=Nil; end; sStream.position:=0; s:=Format('%.*d',[13, uniq]); s:= savedir+'\'+s+'$'+trim(copy(dbase,Lastdelimiter('\',dbase)+1,10))+'-'+tablename+'.db'; sStream.savetofile(s); last1:=inttostr(Lastuniquenumber); sStream.clear; sstream.writestring(format('%4s',['0'])); sstream.writestring(format('%10d',[length(last1)])); sStream.writestring(last1); s:=Format('%.*d',[13, uniq]); s:= savedir+'\'+s+'$pos-'+tablename+'.db'; sStream.savetofile(s); end;
-
Hi I have an httpserver (synapse), which among other things print a short but rather complex . report. Therefore in the Execute part I have put a Critical section Acquire;/Release block (when rinting is required.) I cannot use a Printer:=Tprinter.create in the Execute block because the report creation and printing functions are used also by external EXE (and I cannot figure out to tell the function for the report to use th Printer created inside the thread or the vcl global Printer when it is called by gh external program). After I print a few times i get this error First chance exception at $75B98FC2. Exception class EAccessViolation with message 'Access violation at address 671A7B65 in module 'madExcept32.dll'. Read of address 8BF455D7'. Process Posserver.exe (2480) Is this an error of madexcept of of my program? And if it is from my program would anybody have an idea as ti what i am doing wrong and how to fix it? I hqve attached the log of the entire error message. log.txt
-
VCL or FMX: My sample using Thread running in another forms for some tasks...
programmerdelphi2k posted a topic in General Help
My sample using Thread running in another forms some tasks... not 100% perfect or SAFE... but works if you take a care about my "little code" of course, needs to know "what going on..." and to do some changes for a specific usage... then, dont blame me, this it's just a simple sample. ok? take the idea and do better!!! maybe a "container using Observer Pattern" would help here, but "arrays" was good for me in this time! try close all forms, or simply the mainform 🙂 you CAN click many time on Button and raise yourS threadS... 1x, 2x, 3x, etc... dont abuse :))) // ---- FormMain ----- var MainForm : TMainForm; LHowManyThreadRunning: integer = 0; // Global vars was just for my test... dont use it, at all!!! implementation {$R *.dfm} uses uFormWithThread; var LArrForms: TArray<TForm>; LTop : integer = 0; LLeft : integer = 0; procedure MyDestroyForms; begin for var F in LArrForms do if (F <> nil) then FreeAndNil(F); end; procedure TMainForm.Bnt_Call_Form_ThreadClick(Sender: TObject); var i: integer; begin i := Length(LArrForms); LArrForms := LArrForms + [TFormWithThread.Create(nil)]; LArrForms[i].Top := LTop; LArrForms[i].Left := LLeft; LArrForms[i].Show; // LTop := LTop; LLeft := LLeft + LArrForms[i].Width; end; procedure TMainForm.FormCloseQuery(Sender: TObject; var CanClose: Boolean); begin CanClose := LHowManyThreadRunning = 0; end; procedure TMainForm.FormDestroy(Sender: TObject); begin MyDestroyForms; end; procedure TMainForm.Btn_Try_Close_All_Form_ShowingClick(Sender: TObject); begin for var F in LArrForms do if (F <> nil) then F.Close; end; initialization ReportMemoryLeaksOnShutdown := true; end. // --- Secondary Forms... var FormWithThread: TFormWithThread; implementation {$R *.dfm} uses uMyThread, uFormMain; var LArrThreads: TArray<TMyThread>; function MyCanClose: Boolean; begin result := false; // while (Length(LArrThreads) > 0) do begin // trying kill the thread... LArrThreads[0].Terminate; LArrThreads[0].WaitFor; LArrThreads[0].Free; // // if ok, remove it from list delete(LArrThreads, 0, 1); end; // LHowManyThreadRunning := Length(LArrThreads); result := LHowManyThreadRunning = 0; end; procedure TFormWithThread.Btn_RunThreadClick(Sender: TObject); var i: integer; begin i := Length(LArrThreads); LArrThreads := LArrThreads + [TMyThread.Create(MyUpdateButtonCaption)]; // Memo1.Lines.Add(TimeToStr(now) + ' CurrentThread: ' + TThread.CurrentThread.ThreadID.ToString + ' ... App'); // LArrThreads[i].Start; // LHowManyThreadRunning := LHowManyThreadRunning + 1; MyAnimation.StartAnimation; end; procedure TFormWithThread.FormCloseQuery(Sender: TObject; var CanClose: Boolean); begin LHowManyThreadRunning := Length(LArrThreads); CanClose := LHowManyThreadRunning = 0; // if not CanClose then CanClose := MyCanClose; end; procedure TFormWithThread.MyUpdateButtonCaption(const AValue: string); begin Memo1.Lines.Add(TimeToStr(now) + ' CurrentThread: ' + TThread.CurrentThread.ThreadID.ToString + ' ' + AValue); end; end. unit uMyThread; interface uses System.SysUtils, System.Classes, System.Threading; type TMyProcReference = reference to procedure(const AValue: string); TMyThread = class(TThread) strict private FProc : TMyProcReference; FLCounter : integer; FLThreadID: string; protected procedure Execute; override; procedure DoTerminate; override; public constructor Create(const AProc: TMyProcReference = nil); overload; end; implementation { TMyThread } constructor TMyThread.Create(const AProc: TMyProcReference = nil); begin inherited Create(true); // FProc := AProc; FLThreadID := ThreadID.ToString; FLCounter := 0; end; procedure TMyThread.DoTerminate; begin FLThreadID := ThreadID.ToString; // if Assigned(FProc) then TThread.Queue(nil, procedure begin FProc('This is the end! FLThreadID: ' + FLThreadID + ' LCounter: ' + FLCounter.ToString); end); end; procedure TMyThread.Execute; begin while not Terminated do begin FLThreadID := ThreadID.ToString; // if (FLCounter = 100) then break; // if Assigned(FProc) then TThread.Queue(nil, procedure begin FProc('FLThreadID: ' + FLThreadID + ' LCounter: ' + FLCounter.ToString); end); // // simulating a process... "LCounter just for test n process" FLCounter := FLCounter + 1; sleep(500); end; end; end. -
My "Execute" on Thread is not called anymore... I'm staying crazy and dont see the my error
programmerdelphi2k posted a topic in Algorithms, Data Structures and Class Design
people, My "Execute" on Thread is not called anymore... I'm staying crazy and dont see the my error the thread is created and released with no-errors, etc.. I "breakpoint it" and dont see nothing to happens... I have the same constructions in anothers project and "Execute" is execute"D" and breakpoint is breakpoint"ED" >:) but new projects (units), does not works anymore I'm staying crazy and dont see my error on code.... help me! type TMyThread = class(TThread) private protected procedure Execute; override; public constructor Create; destructor Destroy; override; end; TForm1 = class(TForm) Button1: TButton; procedure Button1Click(Sender: TObject); private public end; var Form1: TForm1; implementation {$R *.dfm} { TMyThread } constructor TMyThread.Create; begin inherited Create; // created (be suspended or not) OK! debug end; destructor TMyThread.Destroy; begin inherited; // destroyed OK! debug end; procedure TMyThread.Execute; begin // the "Execute" is not called anymore... it's jumped, same in Debug mode inherited; // or not... end; procedure TForm1.Button1Click(Sender: TObject); var x: TMyThread; begin x := TMyThread.Create; try // x.Start; // if suspended... finally x.Free; end; end; -
Hi Folks, in one ouf our projects I'm using @Daniele Teti 's loggerpro library (https://github.com/danieleteti/loggerpro) instead of a homebrew logging solution. A few weeks after switching to loggerpro, a first Eurekalog bug report came in with the message: "EMonitorLockException in ThreadSafeQueueU.pas: {ThreadSafeQueueU}TThreadSafeQueue<LoggerPro.TLogItem>.Enqueue, Zeile 157 (0)". This exception is clearly raised inside loggerpro. I have already asked at GitHub (https://github.com/danieleteti/loggerpro/issues/53), but have received no reply yet. Every month or so, another of these bug reports comes in. The problem is: - I cannot reproduce/trigger it on my development PC, even though I think I can locate exactly, where and under which circumstances it happens - I don't see any obvious error in the loggerpro code - I don't see any obvious error in my code which is why I'm asking for help here. Maybe I have missed something obvious in my code... We have the following scenario: The main thread starts a background task (IFuture), which builds up an index of files for later use. Both, main and background task log their status with LoggerPro. The index updater: procedure TUpdater.Update; var LXxxFiles, LYyyFiles: TFileList; begin if FStatus = stNotLoaded then begin Log.Debug('Renewing Index', 'INDEX'); LXxxFiles := TFileList.Create; LYyyFiles := TFileList.Create; try FStatus := stLoading; ... Prepare XXX and YYY lists ... Log.Info('Check %d Xxx Files', [LYyyFiles.Count], 'INDEX'); Log.Info('Check %d Yyy Files', [LXxxFiles.Count], 'INDEX'); // Check existing files and index their content if FStatus <> stCanceled then if Process(LXxxFiles) and Process(LYyyFiles) then FStatus := stLoaded; if FAutoSave then FIndex.Save; FIndex.LogStats; Log.Debug('Status - ' + TRttiEnumerationType.GetName<TLoadStatus>(FStatus), 'INDEX'); finally LXxxFiles.Free; LYyyFiles.Free; end; end; end; If the main task needs the index, it calls the following routine: function TUpdater.WaitForCompletion: boolean; begin Log.Enter('Updater.WaitForCompletion', 'INDEX'); // Waits until the IFuture task is finished and returns its status // The calling thread is blocked while waiting Result := (FTask.Value = stLoaded); Log.Exit('Updater.WaitForCompletion', 'INDEX'); end; Log.Enter and Log.Exit are just two wrapper functions around Log.Debug that I have added to LoggerPro. The Exception occurs on the `Log.Exit` call Here are the relevant lines of the Eurekalog report: EMonitorLockException Object lock not owned. |005B7380|Application.exe|ThreadSafeQueueU.pas |{ThreadSafeQueueU}TThreadSafeQueue<LoggerPro |TLogItem>.Enqueue |157[0] | |005B61B5|Application.exe|LoggerPro.pas |TLogWriter |Log |557[5] | |0110346B|Application.exe|System.Generics.Defaults.pas | | |39[0] | |010FF5A2|Application.exe|Update.Index.pas |TUpdater |WaitForCompletion |845[4] | |010FF560|Application.exe|Update.Index.pas |TUpdater |WaitForCompletion |841[0] | Normally the update task takes some time, so the typical log output is: 2022-04-21 15:22:13:937 [TID 16780][INFO ] [INDEX ] Updater.Update in: C:\Users\Public\Documents\##### 2022-04-21 15:22:13:937 [TID 16780][DEBUG ] [INDEX ] --> Updater.StopUpdate 2022-04-21 15:22:13:937 [TID 16780][DEBUG ] [INDEX ] <-- Updater.StopUpdate 2022-04-21 15:22:13:987 [TID 16780][INFO ] [INDEX ] Contains 240 Files 2022-04-21 15:22:13:987 [TID 16780][INFO ] [INDEX ] Contains 4931 Entries 2022-04-21 15:22:13:987 [TID 3280][DEBUG ] [INDEX ] Renewing Index 2022-04-21 15:22:13:987 [TID 16780][DEBUG ] [INDEX ] --> Updater.WaitForCompletion 2022-04-21 15:22:14:080 [TID 3280][INFO ] [INDEX ] Remove 0 Files 2022-04-21 15:22:14:080 [TID 3280][INFO ] [INDEX ] Check 238 xxx Files 2022-04-21 15:22:14:080 [TID 3280][INFO ] [INDEX ] Check 2 yyy Files 2022-04-21 15:22:14:242 [TID 3280][INFO ] [INDEX ] Contains 240 Files 2022-04-21 15:22:14:242 [TID 3280][INFO ] [INDEX ] Contains 4931 Entries 2022-04-21 15:22:14:242 [TID 3280][DEBUG ] [INDEX ] Updater.Status - stLoaded 2022-04-21 15:22:14:242 [TID 16780][DEBUG ] [INDEX ] <-- Updater.WaitForCompletion ... Normal work continues here In some cases (no search paths defined or search paths empty), there's "nothing" to do, which results in the following log output: 2022-04-21 14:18:14:972 [TID 22208][INFO ] [INDEX ] Updater.Update in: C:\Users\Public\Documents\##### 2022-04-21 14:18:14:972 [TID 22208][DEBUG ] [INDEX ] --> Updater.StopUpdate 2022-04-21 14:18:14:972 [TID 22208][DEBUG ] [INDEX ] <-- Updater.StopUpdate 2022-04-21 14:18:14:973 [TID 22208][INFO ] [INDEX ] Contains 0 Files 2022-04-21 14:18:14:973 [TID 22208][INFO ] [INDEX ] Contains 0 Entries 2022-04-21 14:18:14:974 [TID 14984][DEBUG ] [INDEX ] Renewing Index 2022-04-21 14:18:14:974 [TID 14984][INFO ] [INDEX ] Remove 0 Files 2022-04-21 14:18:14:974 [TID 14984][INFO ] [INDEX ] Check 0 xxx Files 2022-04-21 14:18:14:974 [TID 14984][INFO ] [INDEX ] Check 0 yyy Files 2022-04-21 14:18:14:977 [TID 14984][INFO ] [INDEX ] Contains 0 Files 2022-04-21 14:18:14:977 [TID 14984][INFO ] [INDEX ] Contains 0 Entries 2022-04-21 14:18:14:977 [TID 14984][DEBUG ] [INDEX ] Updater.Status - stLoaded 2022-04-21 14:18:14:979 [TID 22208][DEBUG ] [INDEX ] --> Updater.WaitForCompletion 2022-04-21 14:18:14:979 [TID 22208][DEBUG ] [INDEX ] <-- Updater.WaitForCompletion ... Normal work continues here Note that in this case the updater was finished (stLoaded) before WaitForCompletion was called. The Log.Enter "--> Updater.WaitforCompletion" line may occur anywhere between the lines of the background thread (TID 14984 in this case). This is the LoggerPro output matching the bug report. The `EMonitorLockException` occured on the `Log.Exit` call in `TUpdater.WaitForCompletion` and this line is missing from the log: 2022-04-21 14:42:03:003 [TID 20620][INFO ] [INDEX ] Updater.Update in: C:\Users\Public\Documents\##### 2022-04-21 14:42:03:003 [TID 20620][DEBUG ] [INDEX ] --> Updater.StopUpdate 2022-04-21 14:42:03:003 [TID 20620][DEBUG ] [INDEX ] <-- Updater.StopUpdate 2022-04-21 14:42:03:004 [TID 20620][INFO ] [INDEX ] Contains 0 Files 2022-04-21 14:42:03:004 [TID 20620][INFO ] [INDEX ] Contains 0 Entries 2022-04-21 14:42:03:004 [TID 3312][DEBUG ] [INDEX ] Renewing Index 2022-04-21 14:42:03:004 [TID 3312][INFO ] [INDEX ] Remove 0 Files 2022-04-21 14:42:03:004 [TID 3312][INFO ] [INDEX ] Check 0 xxx Files 2022-04-21 14:42:03:004 [TID 3312][INFO ] [INDEX ] Check 0 yyy Files 2022-04-21 14:42:03:008 [TID 20620][DEBUG ] [INDEX ] --> Updater.WaitForCompletion 2022-04-21 14:42:03:008 [TID 3312][INFO ] [INDEX ] Contains 0 Files 2022-04-21 14:42:03:008 [TID 3312][INFO ] [INDEX ] Contains 0 Entries 2022-04-21 14:42:03:008 [TID 3312][DEBUG ] [INDEX ] Updater.Status - stLoaded ... Normal work continues here Note that the updater was still working (on nothing ;-)) when WaitForCompletion was called. It looks like Log.Exit('WaitForCompletion') and Log.Debug('Updater.Status - stLoaded') happen in the same millisecond, so I assume that thread 3312 still held the lock, when exception thread 20620 called `Log.Exit`. But I see this all the time (finish/exit happens in the sme millisecond) when I run the code on my PC and never get an EMonitorLock exception. Is there something we are doing wrong or have we come across a race condition in LoggerPro or the Delphi locking implementation?
-
The following code program ThreadOSError; {$APPTYPE CONSOLE} uses System.SysUtils, System.Classes; begin Assert(GetLastError=0); TThread.CreateAnonymousThread(procedure begin try CheckOSError(GetLastError); except On E: Exception do WriteLn(E.Message); end; end).Start; ReadLn; end. produces the following output in 10.3,3 in Windows. System Error. Code: 87. The parameter is incorrect Same is true whichever way you run Thread code. Is this a known issue? Any idea why the OS error is raised?