#1 2013-08-13 01:19:16

ncook
Member
From: Australia
Registered: 2013-08-13
Posts: 19

How to safely terminate the TSQLRestClientURI OnIdle background thread

I've been experimenting with the TSQLRestClientURI.OnIdle background communications and it's working really well. Thanks for that feature, as it helps to make the client applications much more responsive.

However there are some situations where a long running wait may need to be prematurely terminated (for example: when the user wants to cancel the pending operation, of even wants to close the client).

Is there a safe mechanism for the client application to be able to terminate the background thread (in TSQLRestClientURI) that is waiting for the server to respond? (rather than just waiting for it to time out)

ncook

Offline

#2 2013-08-13 09:30:24

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,659
Website

Re: How to safely terminate the TSQLRestClientURI OnIdle background thread

There is sadly not such safe mechanism to interrupt the background thread.
The background process has to be killed safely.... which is not possible by design.

We may terminate the process by killing the background thread..
But I'm not convinced it will be safe: resources may be lost (e.g. finally blocks may be never reached).

What do you propose as implementation pattern?

Offline

#3 2013-08-13 14:10:14

ncook
Member
From: Australia
Registered: 2013-08-13
Posts: 19

Re: How to safely terminate the TSQLRestClientURI OnIdle background thread

Would it be possible to add a third argument to TOnIdleSQLRestClient, a Boolean which if set True would terminate the waiting thread.
Something like TOnIdleSQLRestClient = procedure(Sender: TSQLRestClientURI; ElapsedMS: Integer; out Terminate: Boolean) of object;

This would have the advantage of:
(a) only terminating while still in a wait state, and
(b) leaving the termination up to the framework itself, which could ensure it was done as safely as possible.

As far as the UI, I'm envisaging something like a "Cancel" button on the "Please wait..." form displayed by the OnIdle event. (e.g. the user has decided they don't want to wait, and would rather cancel the operation).
It would then be up to the application to capture the intent to terminate the wait, and feed that back to something the OnIdle event handler could use to achieve that end (e.g. by setting the Terminate argument).

I'm not sure if that is practical or not, but I'm thinking about the frustration caused by similar extended waits that occur sometimes in other applications (e.g. Windows attempting to copy a file over a bad network connection) that seem to go on forever, with no way for the user to say "Give up! There's obviously something wrong. If it's going to take that long I don't care any more." For half my users, such extended waits usually end up with them killing the application in Task Manager (or worse: pulling the power cord).

Anything we can do to prevent that level of frustration is good. The OnIdle event helps because it keeps the application responsive. But at present it still does not give the user any alternative but to wait (or out of frustration, to take more drastic action).

Offline

#4 2013-08-13 15:36:35

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,659
Website

Re: How to safely terminate the TSQLRestClientURI OnIdle background thread

If I understand correctly, your proposal is that, when the OnIdle method notifies a termination, the background thread is let down, and will finish his work in the background.
Then a new background thread instance is to be used for the next call (e.g. after re-connection).

This make sense to me.
Pulling the power cord is indeed not a good solution. wink

But I still can see a potential issue: the whole TSQLRestClientURI is to be re-created, otherwise we may have GPF from the background thread.
In this case, we may have a memory leak: who will be responsible of releasing the "old" TSQLRestClientURI instance?
We have to investigate about this.
I propose to add an optional ForceOnTerminate parameter, in which OnIdle could be able to set a method to release the background resource - e.g. the TSQLRestClient.Free method. If it is nil, it won't be interrupted.

If we commit such an enhancement, are you OK about helping us for the testing on your side?

Offline

#5 2013-08-15 02:06:32

ncook
Member
From: Australia
Registered: 2013-08-13
Posts: 19

Re: How to safely terminate the TSQLRestClientURI OnIdle background thread

Sorry, I got a bit lost in your third paragraph. I'm only new to the mORMot framework, and have only been experimenting with it for a month or so. I'm still at the "let's try this and see if I can make it work" stage, and so some of the details are a bit beyond my current level of understanding, at least without more time to digest them. (I'm also fighting a two week head cold, so my concentration level is not a good as it should be at the moment.)

Having said that, I would be quite happy to do some testing of any proposed technique that you decide to try. My testing would not be deep, as I am very new to the concepts of multi-threading, especially in Delphi (I have never tried multi-threaded programming in Delphi before my first mORMot server application, only about a month ago), but I could certainly test how well a given implementation works in variations of our application environment, as well as checking for memory leaks, and giving feedback on practical implementation issues (once I understand them properly).

You mentioned needing to recreate the TSQLRestClientURI to avoid a GPF from the background thread. As I said, I'm not entirely clear at this stage about why that would be required, so I'll take your word on it.
However our client application architecture has been built to easily drop and recreate the TSQLModel, TSQLRestClientURI and the service interfaces, regularly or on demand, as this seemed like the best way to handle server drop-outs and/or the fail-over of servers to new addresses. So while I can see that recreating the TSQLRestClientURI may be a problem for a really simple application, it shouldn't be much of a problem for a production ready architecture, which is where the issue would arise in the first place.

Last edited by ncook (2013-08-15 02:23:38)

Offline

#6 2013-12-07 22:01:54

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,659
Website

Re: How to safely terminate the TSQLRestClientURI OnIdle background thread

What about recreating yourself the TSQLRestClientURI class in case of failure?

Offline

Board footer

Powered by FluxBB