Sonjli 6 Posted May 3, 2019 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 Ā Ā Ā Share this post Link to post
Primož GabrijelÄiÄ 227 Posted May 8, 2019 I don't really understand your questions, sorry. Ā If you run some external code, you cannot be sure if it is thread-safe. You should protect access to it with some synchronization mechanism.Ā Ā A whole idea of a guardian object with a "not responding" callback is newĀ to me. I don't believe it is a commonly used pattern. I can't comment on it as I never used it in practice. Share this post Link to post
Sonjli 6 Posted May 9, 2019 Hi Primoz, yes, my example is not so clear. My idea is of making something like a "Guardian\watchdog" (ok, they are not the same...) service who calls an url every X seconds, and if it does not respond then it delegates the calling service to do whatever it wants (it can, for example, stop the running service and restart). I thought the solution was of using the "OnMessage" technique and delegates there the calling service. I don't know if this is the right pattern, nor the right solution, indeed. I hope to be more clear... Thanks Share this post Link to post
Primož GabrijelÄiÄ 227 Posted May 9, 2019 (edited) Yes, OnMessageis designed for this. Ā OTL takes care that OnMessage handler is executed in the thread which created the background task (in the owner). Edited May 9, 2019 by Primož GabrijelÄiÄ typo 1 Share this post Link to post