ITask.ContinueWith

Fore Syntax

ContinueWith(Action: ITaskAction; Options: TaskContinuationOptions): ITask;

Fore.NET Syntax

ContinueWith(Action: Prognoz.Platform.Interop.ForeSystem.ITaskAction; Options: Prognoz.Platform.Interop.ForeSystem.TaskContinuationOptions): Prognoz.Platform.Interop.ForeSystem.ITask;

Parameters

Action. Action that is executed when the created task is started.

Options. Condition for executing the following task.

Description

The ContinueWith method creates an action execution task, which starts depending on the result of the current task, and adds it to task queue.

Comments

An instance of custom class object implemented by the ITaskAction interface must be specified as the value of the Action parameter. The Action method of the specified interface is called after executing the current task according to condition specified in the Parameters parameter.

All queue tasks must be added synchronously, that is, the Parameters parameter must consist of the combination of the TaskContinuationParameters.ExecuteSynchronously value and execution condition. This means that each task waits till all the tasks added to its queue are completed. Tasks can also be used get parameters of the task, to the queue of which they are added. Values are divided by the OR keyword.

Fore Example

Executing the example requires a form with two buttons on it. The first button is used to create and start tasks, the second one returns execution results. The repository contains a connection to database with the DB identifier.

Class TESTForm: Form
    Button1: Button;
    Button2: Button;
    Task1, Task2, Task3: ITask;

    Sub Button1OnClick(Sender: Object; Args: IMouseEventArgs);
    Var
        MB: IMetabase;
        DBInst: IDatabaseInstance;
        SC: ISecurityConnection2;
        SCAsync: ISecurityConnection;
        Command: IDalCommand;
        DalTask: IDalCommandTask;
        Next1: OneTaskAction;
        Next2: TwoTaskAction;
    Begin
        MB := MetabaseClass.Active;
        DBInst := MB.ItemById("BD").Open(NullAs IDatabaseInstance;
        SC := DBInst.Connection As ISecurityConnection2;
        //Test whether connection supports working in asynchronous mode
        If SC.Type <> DalConnectionType.Async Then
            SCAsync := SC.Clone(DalConnectionType.Async);
        End If;
        //Data extraction command
        Command := SCAsync.CreateCommand("");
        //...adjust Command parameters
        //Create a task for executing SQL query
        DalTask := (Command As IDalCommand2).CreateTask(DalCommandExecuteType.CreateCursor);
        Task1 := DalTask As ITask;
        //Create tasks that will be started after Task1 has completed
        //Task executed if Task1 was successfully completed
        Next1 := New OneTaskAction.Create;
        Task2 := Task1.ContinueWith(Next1, TaskContinuationOptions.ExecuteSynchronously Or TaskContinuationOptions.OnlyOnRanToCompletion);
        //Task executed if Task1 completes with some error
        Next2 := New TwoTaskAction.Create;
        Task3 := Task1.ContinueWith(Next2, TaskContinuationOptions.ExecuteSynchronously Or TaskContinuationOptions.OnlyOnFaulted);
        Task1.Start;
    End Sub Button1OnClick;

    Sub Button2OnClick(Sender: Object; Args: IMouseEventArgs);
    Var
        Result1: IDalCommand;
        Result2, Result3: Variant;
    Begin
        //Results of Task1
        If Task1.IsCompleted And (Task1.State = TaskState.RanToCompletion) Then
            Result1 := (Task1 As IDalCommandTask).Result;
            //...
        End If;
        //Results of Task2
        If Task1.IsCompleted And (Task1.State = TaskState.RanToCompletion) Then
            Result2 := Task2;
            //...
        End If;
        //Results of Task3
        If Task1.IsCompleted And (Task1.State = TaskState.RanToCompletion) Then
            Result3 := Task3;
            //...
        End If;
    End Sub Button2OnClick;

End Class TESTForm;

Class OneTaskAction: Object, ITaskAction
    Public Function Action(Antecedent: ITask): Variant;
    Var
        //...
        Result: Variant;
    Begin
        //Operation executed if the Task1 is completed successfully
        Result := ...
        Return Result;
    End Function Action;
End Class OneTaskAction;

Class TwoTaskAction: Object, ITaskAction
    Public Function Action(Antecedent: ITask): Variant;
    Var
        //...
        TaskException: IException;
        Result: Variant;
    Begin
        //Operation executed if  Task1 completes with error
        //...
        //Error occurred on executing the Task1 task
        TaskException := Antecedent.Exception;
        //...
        Result := ...
        Return Result;
    End Function Action;
End Class TwoTaskAction;

After starting the form, clicking the first button creates three tasks. The first task executes an SQL query asynchronously. The second or the third task is started depending on the result of the first task. The second task is executed if the first one completed successfully. The third task is executed if the first one completed with error. Using the Antecedent parameter in the third task, it is possible to get parameters of the first task, including its runtime error.

On clicking the second button the user can get and process task results.

Fore.NET Example

Executing the example requires a .NET form with two buttons on it. The first button is used to create and run tasks, the second one returns execution results. The repository contains a connection to database with the DB identifier.

Imports Prognoz.Platform.Forms.Net;
Imports Prognoz.Platform.Interop.Dal;
Imports Prognoz.Platform.Interop.Db;
Imports Prognoz.Platform.Interop.ForeSystem;
Imports Prognoz.Platform.Interop.Metabase;

Public Partial Class TESTForm: Prognoz.Platform.Forms.Net.ForeNetForm
    Public Constructor TESTForm();
    Begin
        InitializeComponent();
    End Constructor;
    Task1: ITask;
    Task2: ITask;
    Task3: ITask;

    Private Sub button1_Click(sender: System.Object; e: System.EventArgs);
    Var
        MB: IMetabase;
        DBInst: IDatabaseInstance;
        SC: ISecurityConnection2;
        SCAsync: ISecurityConnection;
        Command: IDalCommand;
        DalTask: IDalCommandTask;
        Next1: OneTaskAction;
        Next2: TwoTaskAction;
    Begin
        MB := Self.Metabase;
        DBInst := MB.ItemById["BD"].Open(NullAs IDatabaseInstance;
        SC := DBInst.Connection As ISecurityConnection2;
        //Test whether connection supports working in asynchronous mode
        If SC.Type <> DalConnectionType.dctAsync Then
            SCAsync := SC.Clone(DalConnectionType.dctAsync);
        End If;
        //Data extraction command
        Command := SCAsync.CreateCommand("");
        //...adjust Command parameters
        //Create a task for extracting data
        DalTask := (Command As IDalCommand2).CreateTask(DalCommandExecuteType.daextyCreateCursor);
        Task1 := DalTask As ITask;
        //Create tasks that will be started after Task1 has completed
        //Task executed if Task1 was successfully completed
        Next1 := New OneTaskAction();
        Task2 := Task1.ContinueWith(Next1, TaskContinuationOptions.tacoopExecuteSynchronously Or TaskContinuationOptions.tacoopOnlyOnRanToCompletion);
        //Task executed if Task1 failed with error
        Next2 := New TwoTaskAction();
        Task3 := Task1.ContinueWith(Next2, TaskContinuationOptions.tacoopExecuteSynchronously Or TaskContinuationOptions.tacoopOnlyOnFaulted);
        Task1.Start();
    End Sub;

    Private Sub button2_Click(sender: System.Object; e: System.EventArgs);
    Var
        Result1: IDalCommand;
        Result2, Result3: Object;
    Begin
        //Results of Task1
        If Task1.IsCompleted And (Task1.State = TaskState.atsRanToCompletion) Then
            Result1 := (Task1 As IDalCommandTask).Result;
            //...
        End If;
        //Results of Task2
        If Task1.IsCompleted And (Task1.State = TaskState.atsRanToCompletion) Then
            Result2 := Task2;
            //...
        End If;
        //Results of Task3
        If Task1.IsCompleted And (Task1.State = TaskState.atsRanToCompletion) Then
            Result3 := Task3;
            //...
        End If;
    End Sub;

End Class;

Class OneTaskAction: ITaskAction
    Public Function Action(Antecedent: ITask): Object;
    Var
        //...
        Result: Object;
    Begin
        //Operation executed if the Task1 is completed successfully
        Result := ...
        Return Result;
    End Function Action;
End Class OneTaskAction;

Class TwoTaskAction: ITaskAction
    Public Function Action(Antecedent: ITask): Object;
    Var
        //...
        TaskException: IException;
        Result: Object;
    Begin
        //Operation executed if  Task1 failed with error
        //...
        //Error occurred on executing the Task1 task
        TaskException := Antecedent.Exception;
        //...
        Result := ...
        Return Result;
    End Function Action;
End Class TwoTaskAction;

After starting the form, clicking the first button creates three tasks. The first task executes an SQL query asynchronously. The second or the third task is started depending on the result of the first task. The second task is executed if the first one is completed successfully. The third task is executed if the first one is completed with error. Using the Antecedent parameter in the third task, it is possible to get parameters of the first task, including its runtime error.

On clicking the second button the user can get and process task results.

See also:

ITask