This post is a supplement to my video from last week, so if you watched my video, you won’t find much new in this post, but I know that there are some of you that prefer the written word so here we go 😁

One of the biggest problems at the moment in Business Central is performance, and one of the ways that you would improve performance in other applications is by making your applications multi-threaded. However this has not really been an option in NAV because NAV is not multi-threaded, now I know one of the ways that you can create a sort of multi-threading in NAV is to offload tasks to the job ques, and while this works it is a complicated way of increasing performance. But have no fear Microsoft has finally created a way of doing multi-threading sort of 🙃. The reason why I say sort of is because, if you expect that Business Central now is 100% multi-threaded, you will sadly be disappointed, because there are some limitations to what you can do, which are the following.

  1. You can only have 5 background tasks running at any given time, if you try to start more they will be queued.
  2. You can only perform read operations.
  3. The background task is tired to a page, which means if you close the page that started the task, then the task will be canceled.
  4. If the record ID is changed the task will be canceled.

Besides these limitations page background tasks great 😀. So how can I use Page Background Tasks? Well, the idea behind Page Background Tasks is that you can offload long-running tasks from the main thread (the UI Thread) unto another thread, thereby not locking the user interface, which in turn means that the user can still use the system without having to wait. So let us take a look at some code 🤓 you can find all the source code here. https://dfredborg.visualstudio.com/Business%20Central/_git/Business%20Central?version=GBPageBackgroundTasks&path=%2FMyPageBackgroundTask.cod.al

First of you need to create a very simple codeuint.

codeunit 50100 MyPageBackgroundTask
{
    trigger OnRun()
    var
        Result: Dictionary of [Text, Text];
        SalesLine: Record "Sales Line";
        Total: Decimal;
    begin
        // Run some code
        if SalesLine.FindSet() then
            repeat
                Total := Total + SalesLine.Amount;
            until SalesLine.Next() = 0;

        Result.Add('Total', format(Total));

        Page.SetBackgroundTaskResult(Result);
    end;
}

So in this codeuint I have created a variable of type Dictionary, which is the way that you can communicate between your page and your codeunit, here it is important that your Dictionary is Text, Text because this is the only structure that is supported by Page Background Tasks. Once you have written your logic and added it to your Dictionary, you must call Page.SetBackgroundTaskResult passing your Dictionary.

Next, we will create our page which could look as follows:

pageextension 50100 SalesOrderExt extends "Sales Order"
{
    layout
    {
        addlast(General)
        {
            field(Total; Total)
            {
                Editable = false;
                ApplicationArea = all;
            }
        }
    }


    var
        Total: Text;
        WaitTaskId: Integer;


    trigger OnAfterGetRecord()
    var
        //Defines a variable for passing parameters to the background task
        TaskParameters: Dictionary of [Text, Text];
    begin
        TaskParameters.Add('Wait', '1000');
        //TaskID, CodeunitId, Parameters, Timeout, ErrorLevel
        CurrPage.EnqueueBackgroundTask(WaitTaskId, 50100, TaskParameters, 1000, PageBackgroundTaskErrorLevel::Error);
    end;


    trigger OnPageBackgroundTaskCompleted(TaskId: Integer; Results: Dictionary of [Text, Text])
    begin
        if (TaskId = WaitTaskId) then begin
            Total := Results.Get('Total');
        end;
    end;
}

Here you must create a global Integer I have called mine WaitTaskId, you do not need to assign any value to this Integer, but you must have it, since it holds your task ID, on the OnAfterGetRecord trigger you must declare a Dictionary which you can assign some values that you wish to pass to the task codeunit. Next, you must call CurrPage.EnqueueBackgroundTask where you define your TaskID the codeunit that you wish to execute, your parameters, a timeout if you wish to avoid your task running for too long and the error level, at which level you wish your task to fail. Next, you must define a trigger called OnPageBackgroundTaskCompleted in which you handle the result.

And that is all there is to background tasks, now like a wrote earlier it is not 100% multi-threading but it is a step in the right direction and I am looking forward to seeing if we will see more, however, I do not believe that it is going to happen any time soon, because one of the biggest problems with implementing multi-threading in Business Central is that is so tightly coupled with the database, which makes it nearly impossible to allow write transactions in background tasks, which means Microsoft would have to rewrite the core of Business Central to be Object Orientated 🤔

Leave a Reply