EROTimeout in TROAsyncRequest.ReadResponse

We have calls that may take hours to complete and have been using the classical way to deal with this, which is to increase the timeout.
This works but it’s annoying to wait that long for a true “connection lost” scenario so I have started using the Async way of doing things, like this:

      var Request :=
        FAsyncService.BeginLengthyCall(Param1, Param2, Param3,
        procedure (const aRequest: IROAsyncRequest)

      var TotalWaitTime := 0;
      while not Request.Done and (TotalWaitTime < 4 * 60 * 60  * 1000) do
        Inc(TotalWaitTime, 500);

      if Request.Done then
        ResultValue := FAsyncService.EndLengthyCall(OutParameter, Request);
        raise EMyTimeout.Create('Timeout waiting for LengthyCall completion');

While this works when LengthyCall is responding fast (say less than 10 minutes), I sometimes get EROTimeout exceptions when the call has waited for about 3 hours.
This is the call stack that I get:

uROAsync                          497   +8 TROAsyncRequest.DoReadResponse
uROAsync                          548   +1 TROAsyncRequest.ReadResponse
MyServerLibrary_Intf            10200   +1 TMyService_AsyncProxyEx.EndLengthyCall
MyUnit                            837  +30 TMyClass.DoSomething

It’s as if the server part (or client part) had given up on the call and does not cope with it well.
Does this ring a bell?


I can suggest to use AsyncEx version of service.
advantages: you shouldn’t wait for answer - callback method will be fired automatically.

you can review the Phone Photo Server sample. it demonstrates usage of AsyncEx methods.

I realize that it was not clear in my message above, but I’m already using the AsyncEx methods, with an empty callback, I agree.
What I want is for TMyClass.DoSomething to wait for the async call to complete, hence its own internal loop.
And if I read things correctly, the callback will be triggered when the call has completed, but I still have to call EndLengthyCall to get the result and out parameters. And it is this call that is sending me the EROTimeout exception.


what channel are you using for communication?

This is with TROSynapseSuperTCPChannel as it’s been way more reliable for us than the Indy based.

for supertcp protocol this means that something was happened between server and client and internal ping/pong packages weren’t delivered correctly.

You may try to use TROSuperTCPChannel - this was written similar to synapse but has SSL 1.1 support. but I think, the same situation with EROTimeout can be reproduced …

of course, you can get access to error (TROAsyncRequest.AsyncException) but you can just call end* method and get error here.

Well, yes, that’s exactly what happens because there are connectivity issues in the network I’m using.
But I thought that this was exactly the purpose of the Async interface in that it would simply be bling to micro interruptions at the network level because it does not keep the connection up.
As it turns out, this is not the case and I’ll have to go back to the previous method.


with AsyncEx interfaces you can silently process exceptions and repeat request some times.
for example, if it fails at the 1st attempt, you can repeat the same request up to, say, 5 times.