-
Content Count
110 -
Joined
-
Last visited
Everything posted by Sonjli
-
Ok, thank you as usual. So, I have this strange behavoiur: The task receiving messages sometimes slow very down, and I can see 30/40 messages queued from the "external" thread, but only one elaboration of my task loop. So in this situation the queue risks to be full very quickly (1000 messages I read in docs). But I don't know why this happens... a loop too thight?
-
Hello, I have a task which dies unexpectedly and I don't know how to check this situation. I know for sure it is something related with my software. I added all the "try\except" needed to catch the exception but the task dies the same. The task (I will call it "Child") is created by a MainTask, but when the child dies, the father continues without problems. The Main Task creates a lot of this Child. Every child is good isolated. There are not concurrent resources used between them. The child task contains an infinite loop testing the task.terminated. The child task is added to a TaskGroup and I tested that when it "dies bad" also disappear from TaskGroup. The "OnTerminated" on child does not trigger in this scenario. The child thread never call the OnTerminated, neither in "good termination" case. I don't know why. I don't know how to catch the "FatalException" of the child. How can I test this? I don't know how many other infos you need. Thanks, Eddy
-
To kill the "childs" I do this: FCancellationToken.Signal; FPlugsGroup.WaitForAll; FPlugsGroup is the group for the childs
-
Don't sorry, it's me the one bothering... The OnTerminated is not called even when everything goes right. The strange thing is that the messaging system (task.comm and OnMessage) is perfectly ok.
-
Thank you very much for the fast response. Naturally, this bug don't comes with debugging but in real production from customer... I'll try the logging solution. Thanks again. ps: any idea for the OnTerminated event in the child task?
-
Hi, I have a small task where I use this technique: CreateTask( procedure(const Task: IOmniTask) var lPlugObject: IPluggable; begin ... lPlugObject := FPlugProtocolFactory(lTaskPlugAndParams); // Can I use this? lPlugObject.Stoppable := function: Boolean begin result := Task.Terminated or Task.CancellationToken.IsSignalled; end; lPlugObject.Connect; lPlugObject.Run; ... end) ... The PlugObject has an infinite loop inside the Run method, and sometimes it checks the mothod "Stoppable". PlugObject is a plain object without threads or task, only a "repeat until false" loop. I need to know if this use of anonymous can create problems with the threading concurrency in some way. Thanks, Eddy
-
Yes, in my tests I found some strange behaviours within the omnitask and reference counting, very hard to explain and to test. But after days of pain I found the problem, and I am pretty sure it is not related to Omni or Spring. I am writing a microservices framework with mqtt using a library with some problems with threading... Thanks and keep up the good job Eddy
-
Hi all, I perfectly know the error in subject. It is due of an ancestor form\datamodule missing in the project (don't go deep in all other sub-cases this error can happen...). In my dpr I have all of the ancestors, and if I open them in IDE in the correct order (grandfather - father - child) everything is fine. BUT if I open only a "child" then this error happens. My project is a bit complicated (I make use of injection, threads, etc.) but this simple error is making me and my team crazy. Any idea how to solve this situation? The object tree is something like: TBaseDatamodule |- TChildDatamodule |-- TConcreteDatamodule Thanks in advance, Eddy
-
I can try...
-
Ok,I tried but they are all ok...
-
sorry... what!? I have the register only on frames, not on TdataModules, am I wrong?
-
Ciao Uwe, I try asap... never touched the dproj :B thanks
-
Sorry @Kas Ob. but my problem is at designtime, not runtime. The problem happens in IDE. thanks.
-
My dpr is not exactly canonical... so, is there any problem with IDE ancestor resolution and "strange" disposition of dpr code? For example I have a wrapper object for "Application", so there is no standard Application.createForm(); Application.Initialize; Application.Run; Can this be a problem? I didn't try to make a cosole app (my apps are similar to console applications) with my datamodules, in fact... I can try
-
Everything is exactly as you write. Every datamodule is correctly declared in dpr with path and comment. Real code: ... UInterfacedDataModule in '..\..\..\Model\UInterfacedDataModule.pas' {DMInterfacedDatamodule: TDataModule}, UDMCustomModel in '..\..\..\UDMCustomModel.pas' {DMCustomModel: TDataModule}, UDMUniModel in '..\..\..\Model\UniModel\UDMUniModel.pas' {DMUniModel: TDataModule}, ...
-
Hi, I need to schedule some actions when the time arrives. Something like Windows scheduler does. For example at 12.00am of every day I have to post a rest call on a web site, or at 2.00pm another task. I know it is simple to do it with a standard timer or a polling on system time, but is there a smart solution with OTL? Thanks in advance.
-
Because I need to be in strict control with the scheduling and I am in cross development (Linux and Windows at least). Interesting... any example? I know I can do something like this in OTL, so a "standard" example could help me to figure out.
-
Hi guys, I hope this is the right topic to place my doubts. I use a DLL written in C and it need some work with pointers. I admit I am not very prepared with pointers (scholastic remembrances), so I hope my question to be clear. I have this structure: PODBALMMSG2 = ^ODBALMMSG2; ODBALMMSG2 = packed record alm_no: LongInt; atype: SmallInt; axis: SmallInt; dummy: SmallInt; msg_len: SmallInt; alm_msg: array [0 .. 63] of AnsiChar; end; And this is the function I use to populate this structure and read it: procedure TRdAlmMsgActionA.InternalRdAlmMsg; var iAlarm: Integer; LErrorCounter: Integer; rn: SmallInt; popmsg: PODBALMMSG2; begin FPath := ''; LErrorCounter := 0; // A random number the DLL need to have any initial value rn := 50; try // A pre-filled number with "max paths" (FConnection.MachinePaths) to read from DLL for var J := 1 to FConnection.MachinePaths do begin // A DLL function to loop between "Paths" until "FConnection.MachinePaths" FConnection.ErrHandle := cnc_setpath(FConnection.ConnHandle, J); if FConnection.ErrHandle <> EW_OK then begin Inc(LErrorCounter); Continue; end; // Here I need help: is this algorithm ok? new(popmsg); try // The DLL fill "popmsg" with an array of "PODBALMMSG2" with length "rn" FConnection.ErrHandle := cnc_rdalmmsg2(FConnection.ConnHandle, -1, rn, popmsg); if FConnection.ErrHandle <> EW_OK then begin Inc(LErrorCounter); Continue; end; // Loop for "popmsg" of length "rn" for var I := 0 to rn - 1 do begin // Here I do reading stuff with "popmsg^.alm_no", "popmsg^.aType", etc. // Incremet pointer to read next array value Inc(popmsg); end; finally // Bring the pointer at the start of the array Dec(popmsg, rn); // Free the pointer Dispose(popmsg); end; end; finally cnc_setpath(FConnection.ConnHandle, 0); end; end; I have so many doubts about this: - Have the popmsg pointer to be brought at the start before dispose? - Is the loop right? - Is the "new()" function right to allocate the pointer? - And so on... Any help? Thanks in advance. Eddy
-
Hi, I have this case where one OmniTask run some external code from a delphi library\Component that uses internally a TThread. This thread can't be accessed from outside. This external library have a class which listen for an incoming request and when this happens then it run a "onReceive" event. Something like a listening socket. One OmniTask "run" one and only one of these objects. Have I to pay attention when the "inside-thread" have to use write-resources of the Omnitask? For example when the "inside-thread" need to use the logger of the OmniTask? Some pseudo code: CreateTask( procedure(const task: IOmniTask) var lBroadcaster: IBroadcastManager; lLogger: ILogWriter; begin [...] task.Lock.Acquire; try lLogger.Log(TLogType.Info, 'Testing...', 'TEST'); finally task.Lock.release; end; [...] // lBroadcaster is the object using an internal tthread lBroadcaster.OnReceive := procedure(ABroadcastMessage: IBroadcastMessage) begin task.Lock.Acquire; try try lLogger.Log(TLogType.Info, 'Parsing...', 'TEST'); [...] except on E: Exception do begin lLogger.Log(TLogType.Error, 'Exception (%s): "%s"', [E.ClassName, E.Message], 'TEST'); end; end; finally task.Lock.release; end; end; lBroadcaster.Connect('127.0.0.1', 'guest', 'guest', True); ).SetParameter([...]) // All my stuff injiections .WithLock(CreateOmniCriticalSection) .Run; Is the locking mechanism used in the right way? Thanks Eddy
-
Pointers... loops...
Sonjli replied to Sonjli's topic in Algorithms, Data Structures and Class Design
The API is documented and I used it for years. The my only problem is about pointers... I know, don't say a word 😉 Do you have any Pascal related documentation\manual about pointers? Thanks everybody. Eddy -
Pointers... loops...
Sonjli replied to Sonjli's topic in Algorithms, Data Structures and Class Design
Thank you Anders, really precious. As you see I use the FOCAS library to connect some CNC and sometimes there are some traps... Are you skilled with FOCAS? May I ask you any questions sometimes if I am in danger? 😅 -
Pointers... loops...
Sonjli replied to Sonjli's topic in Algorithms, Data Structures and Class Design
Hi Cristian, thanks for your answer. How do I allocate popmsg? How do I dispose the array? How do I read an element? @popmsg[4].alm_no or popmsg[4]^.alm_no? Eddy -
Hi, simple question: how can I run a pipeline more than one time in the same method\procedure\function? I do like this ... MyPipeline := Parallel .Pipeline .stage(myStage1) .stage(myStage2); ... procedure MyProcedure; begin // First run MyPipeline.Run; MyPipeline.input.Add('ONE'); aValue := MyPipeline.Output.Next; // I tries also this... without success MyPipeline.Cancel; MyPipeline.WaitFor(INFINITE); // I do some stuff in the middle // First run MyPipeline.Run; // Here I receive "Pipeline is already running", but I don't think so... :( MyPipeline.input.Add('TWO'); aValue := MyPipeline.Output.Next; ... end; I am not finding any info in the docs. In the sources of IOmniPipeline I see a "opCountStopped" semaphore that is checked "Assigned" in the first run... but I really don't understand why this limits one instance of a IOmniPipeline to be run only one time in the same method. Thanks again Eddy
-
Hi, sorry for late reading. I am trying to build a kind of a "protocol runner". I need an object which can accept different "actions" and then it can be run in loop to repeat the protocol. Example: Name: "Protocol 1: download a file with locks" 1. Wait until "the other" lock file disappear 2. Put "my" lock file in that folder 3. Download the main file 4. process the main file 5. Delete "my" lock file 7. Wait 5 seconds 8. Restart from 1 The entire loop must be run in a separate non-blocking thread. But every loop must be serialized. I thought that pipeline could be the answer, but I can't run it several times in that loop. I may use a state machine (https://github.com/malcolmgroves/TStateMachine) but I need to build several protocols changing one or more "actions" at runtime... I don't know if this is the right choice. Is my idea clear enough? I hope so... 🙂 Thanks
-
Hi (here again...), I have a doubt about delegation. I have this simple case TWSGuardian = class(...) strict private FOnNotResponding: TProc<Integer>; ... public // Delegation property OnNotResponding: TProc<Integer> read GetOnNotResponding write SetOnNotResponding; end; // OTL task ... Task.Comm.Send(MSG_WSNOTRESPONDING, TOmniValue.CreateNamed(['timeout', LPassedTime])); end; end; end ) .OnMessage(MSG_WSNOTRESPONDING, procedure(const Task: IOmniTaskControl; const msg: TOmniMessage) begin DoNotResponding(msg.MsgData['timeout']); end ); ... procedure TWSGuardian.DoNotResponding(TimeOut: Integer); begin if Assigned(FOnNotResponding) then FOnNotResponding(TimeOut); end; ... When calling the TWSGuardian object I would use a critical section to avoid collisions in case of more than one running TWSGuardian. Like here: begin Grd := TWSGuardian.Create; ... Grd.OnNotResponding := procedure(ATimeOut: Integer) begin if ATimeOut > 1000 then begin // Critical section? RunSomeAlienCode; // How can I be sure this is thread-safe? end; end; ... Grd.Run; ... Grd.Stop; // This safely terminate the task inside TWSGuardian Is this the right way? Is there a common used pattern? How can I move the critical section inside my TWSGuardian instead of using it in the main thread? I am a bit confused. Thanks and sorry for this PITA