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č 223 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č 223 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