Wednesday, July 20, 2011

Life after 2.1: Async redux

OtlParallel unit defines four overloaded Async methods in OTL v2.1:

class procedure Async(task: TProc; taskConfig: IOmniTaskConfig = nil); overload;
class procedure Async(task: TOmniTaskDelegate;
taskConfig: IOmniTaskConfig = nil); overload;
class procedure Async(task: TProc; onTermination: TProc;
taskConfig: IOmniTaskConfig = nil); overload;
class procedure Async(task: TOmniTaskDelegate; onTermination: TProc;
taskConfig: IOmniTaskConfig = nil); overload;

As it turned out, two of them are not necessary anymore. Since the introduction of the taskConfig parameter, termination procedure can also be specified by setting taskConfig.OnTerminated.

To make the matter simpler, I’ve removed both Asyncs that accept the onTermination parameter.

class procedure Async(task: TProc; taskConfig: IOmniTaskConfig = nil); overload;
class procedure Async(task: TOmniTaskDelegate;
taskConfig: IOmniTaskConfig = nil); overload;

The old way of setting termination handler …

  Parallel.Async(
procedure
begin
// executed in background thread
Sleep(500);
MessageBeep($FFFFFFFF);
end,
procedure (const task: IOmniTaskControl)
begin
// executed in main thread
btnAsync.Enabled := true;
end
)
);

… must be replaced with slightly more verbose

  Parallel.Async(
procedure
begin
// executed in background thread
Sleep(500);
MessageBeep($FFFFFFFF);
end,
Parallel.TaskConfig.OnTerminated(
procedure (const task: IOmniTaskControl)
begin
// executed in main thread
btnAsync.Enabled := true;
end
)
);

3 comments:

  1. i have a big problem in my code to call the parallel.Async many times
    i have 6 ActiveX DCOM in Delphi, and wanna call these in same time, to calculate an invoice, so in my exe i work with OTL to async all calls activex, i don't like to wait result or freeze my screen.

    Parallel.Async(
    procedure (const task: IOmniTask)
    var iInnerExc: integer;
    begin
    /// ***********************************************************///
    { return Log}
    TLogSingleton.Instance().Log('Services XX calcul: Début appel.',True);
    //************************* PARALLEL ASYNC ****************************//
    // executed in background thread
    try //
    {Create instance de ViewModel annexes: XXServiceXX}
    mainViewModelPreCalculOTLLevel03 := CreateMainViewModelOTLLevel03Class;
    {Affecter le même Model principal}
    mainViewModelPreCalculOTLLevel03.Model := fModel;
    {Suscribe the observer in list}
    mainViewModelPreCalculOTLLevel03.Provider.Subscribe(fSubscriber);

    {Call VieModel.ServiceXX}
    mainViewModelPreCalculOTLLevel03.StartPrecalcul;
    except on e:exception do
    {call the raise, juste ci dessous, dans le onterminated Handle}
    raise Exception.Create('Exception lors du traitement de Service XX.');
    end;

    end,
    Parallel.TaskConfig.OnTerminated(
    procedure (const task: IOmniTaskControl)
    var excp: Exception;
    begin
    // executed in main thread
    if assigned(task.FatalException) then
    begin
    {expoiler l'exception, captcher ci dessus}
    excp := task.DetachException;
    TErrorSingleton.Instance().Log(Format('Service XX: [Fin TASK Error]. %s:%s',[excp.ClassName, excp.Message]),True);
    FreeAndNil(excp);
    end
    else
    begin
    // executed in main thread
    { return Log}
    TLogSingleton.Instance().Log('Services calcul: [Fin TASK] Fin appel traitement.',True);
    SendNotification([actServiceXXFinish]);
    end;
    end
    )
    );

    this is my call, i repeat it 6 times,

    Parallel.Async(
    CALL01
    );
    Parallel.Async(
    CALL01
    );
    Parallel.Async(
    CALL02
    );

    Parallel.Async(
    CALL06
    );

    i don't need to freeze my application, and i don't need to wait, with

    SendNotification([actServiceXXFinish]); or other Action like "actService01Finish", "actService02Finish"

    i can kown if my traitement is finished or not,

    finnaly, if i write all 6 calls, i will fall in many and many problems, like freeze, and death process,
    but if i write only one call, it will be perfect, i have, my result, and i must say i have one only problem the freeze,

    Conclusion:
    with many calls: problems: freeze, traitement not working, --> kill the process
    with one only call: problems: freeze, no TAniIndicator working (i don't like to work with "sleep")
    the freeze when Delphi enter in the other DLL.

    plz help me


    ReplyDelete
    Replies
    1. Please post OmniThreadLibrary questions at https://en.delphipraxis.net/forum/32-omnithreadlibrary/.

      Delete
    2. thx, my post in :
      https://en.delphipraxis.net/topic/3205-omnithread-delphi-many-calls-in-the-some-function/

      Delete