Wednesday, December 6, 2017

How to create an asynchronous method in D365FO

In d365 for finance and operation a new static method was added to the global class – Global::runAsync()
Let’s create some asynchronous operation:

class SomeClass
{
    public static void main(Args _args)

    {
        SomeClass::runAsync();
    }
}
Ok, Let’s create a table in which the result of each operation will be recorded, a regular table with two fields such as a container and string types. And then launch ten threads for execution. Also, each of the threads created will be written to the list to then check the status of each of them, and after the start of all threads, we will also launch an operation that will check the status of each stream.

public static void runAsync()
{
    System.Threading.Tasks.Task someTask;
    List tasks = new List(Types::Class);
    Counter counter = 0;
    boolean threadsStarting = true;
    for(int i = 0; i < 20; i++)
    {
    // Run Asynchronous task

        someTask = Global::runAsync(
            classNum(SomeClass),
            staticMethodStr(SomeClass, methodRunAsync),
            [‘Async’, int2Str(i)],
            System.Threading.CancellationToken::None,
            classNum(SomeClass),
            staticMethodStr(SomeClass, methodRunAsyncResult));
            tasks.addEnd(someTask);
            counter++;
    }
    //After that, when all task is created, run asynchronous method for
    //check tasks status
    SomeClass::runAfterAllEnded(tasks.pack());
Now let’s simulate our operations, they will be very simple to be easy to understand
CallBack method:

public static void methodRunAsyncResult(AsyncTaskResult _result)
{
    container returnValue;
    SomeTable asyncTable;
    if (_result != null)
    {
        returnValue = _result.getResult();
        str resultstr = conPeek(returnValue, 1);
        Global::info(resultstr);
        ttsbegin;
        asyncTable.FieldString = resultstr;
        asyncTable.FieldContainer = returnValue;
        asyncTable.insert();
        ttscommit;
    }
}
Main method:

public static container methodRunAsync(container _params)
{
    str caller;
    int counter = str2Int(conPeek(_params, 2));
    caller = conPeek(_params, 1);
    caller += ” ” + conPeek(_params, 2);
    System.Threading.Thread::Sleep(1000);
    return([caller]);
}

A method that tracks the status of each stream and, after the execution of the latter, performs some kind of action

public static void runAfterAllEnded(container _params)
{
    boolean threadsRunning = true;
    Counter counter;
    container packedList;
    List tasks = new List(Types::Class);
    for(int i = 3; i < conLen(packedList); i++)
    {
        tasks.addEnd(conPeek(packedList, i+1));
    }

    while (threadsRunning)
    {
        ListEnumerator enumerator = tasks.getEnumerator();
        System.Threading.Tasks.Task currentTask;
        boolean allCompleted = true;

        while(enumerator.moveNext())
        {
            currentTask = enumerator.current();

            if(currentTask.Status == System.Threading.Tasks.TaskStatus::RanToCompletion)
            {
                allCompleted = true && allCompleted;
            }
            else
            {
                allCompleted = false;
                break;
            }
        }
        threadsRunning = !allCompleted;
    }

    SomeTable asyncTable;
    str resultstr = “”;

    while select asyncTable
    {
        str result = “”;

        for (int i = 0; i < conLen(asyncTable.FieldContainer); i++)
        {
            result += conPeek(asyncTable.FieldContainer, i);
        }

        resultstr += result + ” – ” + asyncTable.FieldString + ‘\n’;
    }

    Global::info(resultstr);
}

No comments:

Post a Comment