I followed the example of this post that implements the execution in sequence.
Using example 31 (Project31LongWorkServer), where TLongWorkServiceThread is (of course) a Thread, the worker runs in parallel.
]]>AsynchRedirect start the threads sequentially.
That is, when a second request is made, new "longworker" is queued to start after the completion of the previous one.
Is there any way to run in parallel?
]]>Anyway, this is an example for any other that need use this function (adapted from example 31):
interface declaration:
...
type
ILongWorkCallback = interface(IInvokable)
['{425BF199-19C7-4B2B-B1A4-A5BE7A9A4748}']
procedure WorkFinished(const workName: string; timeTaken: integer);
procedure WorkFailed(const workName, error: string);
end;
ILongWorkService = interface(IInvokable)
['{09FDFCEF-86E5-4077-80D8-661801A9224A}']
procedure StartWork(const workName: string; const onFinish: ILongWorkCallback);
function TotalWorkCount: Integer;
end;
IAsynchLongWorkService = interface(IInvokable)
['{CFA559E5-B181-45BB-84AB-7279DDDA51A9}']
procedure StartWork(const workName: string; const onFinish: Integer);
end;
...
initialization
TInterfaceFactory.RegisterInterfaces([
TypeInfo(ILongWorkService),TypeInfo(ILongWorkCallback),TypeInfo(IAsynchLongWorkService)]);
class declaration:
...
type
TLongWorkService = class(TInterfacedObject,ILongWorkService)
protected
fCallbackInterface: IAsynchLongWorkService;
fDestinationInterface: IAsynchLongWorkService;
public
procedure StartWork(const workName: string; const onFinish: ILongWorkCallback);
function TotalWorkCount: Integer;
end;
TAsynchLongWorkService = class(TInterfacedObject,IAsynchLongWorkService)
protected
fCallback: ILongWorkCallback;
fWorkName: string;
fTotalWorkCount: Integer;
public
procedure StartWork(const workName: string; const onFinish: Integer);
function TotalWorkCount: Integer;
end;
...
class implementation:
...
{ TLongWorkAsyncService }
procedure TLongWorkService.StartWork(const workName: string; const onFinish: ILongWorkCallback);
begin
if fCallbackInterface=nil then begin
fDestinationInterface := TAsynchLongWorkService.Create;
ServiceContext.Request.Server.AsynchRedirect(IAsynchLongWorkService,fDestinationInterface,fCallbackInterface);
end;
onFinish._AddRef; // avoid GPF and the interface is available in asynch. routine
fCallbackInterface.StartWork(workName,Integer(onFinish));
end;
function TLongWorkService.TotalWorkCount: Integer;
begin
result := MaxInt; // this shows the asynchronous functioning
end;
...
{ TAsynchLongWorkService }
procedure TAsynchLongWorkService.StartWork(const workName: string; const onFinish: Integer);
var tix: Int64;
begin
InterlockedIncrement(fTotalWorkCount);
fCallback := ILongWorkCallback(onFinish);
fWorkName := workName;
TSQLLog.Add.Log(sllInfo,'%.Execute(%) started',[self,fWorkName]);
tix := GetTickCount64;
Sleep(5000+Random(1000)); // some hard work
if Random(100)>20 then
fCallback.WorkFinished(fWorkName,GetTickCount64-tix) else
fCallback.WorkFailed(fWorkName,'expected random failure');
TSQLLog.Add.Log(sllInfo,'%.Execute(%) notified',[self,fWorkName]);
fCallback._Release; // release the interface out this function
end;
function TAsynchLongWorkService.TotalWorkCount: Integer;
begin
result := fTotalWorkCount;
end;
Best regards.
]]>Both aDestinationInterface and aCallbackInterface should be of one interface type defined with aGUID.
]]>procedure AsynchRedirect(const aGUID: TGUID; const aDestinationInterface: IInvokable; out aCallbackInterface); overload;
- aGUID: is the source service that I want redirect ? What about the code in the method, must be empty ?
- aDestinationInterface: is any interface where the real process is executed ?
- aCallbackInterface: the aDestinationInterface must have it a callback interface ?
Thanks in advance.
]]>We use it namely for two things:
- when calling callbacks for events notifications: one high-performance main process thread call the virtual interface to mark the event, which is then asynchronously notified in the background to the subscribed clients.
- when adding some information to some slow storage, using a persistence service interface (but we also use AsynchBatch for that).
Thanks.
]]>Thanks in advance.
]]>Thanks in advance.
]]>