web
You’re offline. This is a read only version of the page.
close
Skip to main content

Notifications

Announcements

No record found.

Community site session details

Community site session details

Session Id :
Microsoft Dynamics AX (Archived)

How to load data in form asynchronous?

(0) ShareShare
ReportReport
Posted on by 1,155

Hi community,

Here is my Scenario in AX 2012 R2 CU1:

I have a form where a calculation data on server, pack the data into container and then load the data on client from the container to the form.

Now I want to change the data loading to an asynchronous process to not block the form while loading the data.

My preferred process is:

1. Call the asynchronous process to load the data from form

2. When the asynchronous process finished, there should be a callback to form

3. The triggered call back should load the data from asynchronous filled container to the form

Has anyone a solution, white paper or example from AX standard on how to do it?

Thanks,

Paul

*This post is locked for comments

I have the same question (0)
  • Suggested answer
    Brandon Wiese Profile Picture
    17,788 on at

    There are some built-in examples of doing this in AX. In older versions, the "permissions" form would offload the work of loading its data in another thread and then filling the form after completion, even showing a progress bar while it worked.  Global Search also does some threading to keep the UI thread responsive during long searches.

    You want to use the Thread object.  This has always been very lightly documented, but there are some good blogs out there discussing its use though mostly in older versions of AX.  I have used it in some custom scenarios to offload work, and even sending messages back to the UI thread (since you can not reference any UI element or the infolog from a non-UI thread).

    I'm going to have some need to use Thread in 2012 R2 myself soon.

  • Verified answer
    Brandon Wiese Profile Picture
    17,788 on at

    Here's the MSDN documentation on the Thread class.

    msdn.microsoft.com/.../aa878446(v=ax.50).aspx

    Look in the AOT for Forms\Tutorial_Thread and some classes Tutorial_ThreadWork and TutorialThread.

    Brandon George posts some excellent details over a series of blogs.

    dynamics-ax.blogspot.com/.../dynamics-ax-2009-x-thread-development.html

    dynamics-ax.blogspot.com/.../dynamics-ax-threads-more-details.html

  • Suggested answer
    dolee Profile Picture
    11,279 on at

    Hi,

    You can also consider using the new SysOperation framework in AX2012. Check out how "Asynchronous" and "Reliable Asynchronous" execution mode works in the "Introduction to the SysOperation Framework" whitepaper here. The sample code used in the whitepaper can be found here.

    Cheers

  • Paul Heisterkamp Profile Picture
    1,155 on at

    Hey,

    thank you all for your hints.

    @Brandon Wiese: I will check the usage of Thread Class in combination with setTimeOut(..) method. And a will keep this thread updated with my solution...

    @DOLEE: Yes I had found the SysOperation Framework, but I found no way to perform a callback to form...

    Regards,

    Paul

  • dolee Profile Picture
    11,279 on at

    Hi Paul,

    The example in the whitepaper did the following instead(not exactly a callback):

    1) Assign a unique GUID to the call.

    2) Start the async op, when it's done, it'll create record(s) in a resultTable.

    3) The form will periodically polling the resultTable with the GUID to see whether the process has finished. (Using setTimeOut method. =] )

    You can look at the SysOpFindPrimesForm (in the sample code for the whitepaper) to see how it is implemented.

    Cheers

  • Verified answer
    Brandon Wiese Profile Picture
    17,788 on at

    If you're going to try Thread as a solution, I'll throw in some lessons learned.

    First, some types of objects don't marshal across threads easily.  I recall needing to send a temporary table and having to pack it into a container and unpack it off-thread.

    Here's an example of some code I used from a working AX 4 project.

    This method takes calls on the UI thread and makes the Thread.run(..) call.

    public client static void submitBackground(SendQueue _sendQueue)
    {
    Thread thread;
    ;

    new ExecutePermission().assert();
    thread = new Thread();
    thread.removeOnComplete(true);
    thread.setInputParm([_sendQueue.threadSafe()]); // make thread safe
    thread.run(classnum(SendBase), staticmethodstr(SendBase,SubmitThread));
    CodeAccessPermission::revertAssert();
    }

    This method accepts that call, unpacks the parameters, and makes the off-thread static call.

    public client static void submitThread(Thread _thread)
    {
    SendQueue sendQueue;
    ;

    [sendQueue] = _thread.getInputParm();
    SendBase::submit(sendQueue);
    }

    This is the method that does the off-thread work, but I've trimmed it to show only the callback into the UI thread.  In my case I'm sending back progress information and updating a progress bar.

    public client static void submit(SendQueue _sendQueue)
    {
    int id;
    ;


    [id] = SendBase::progress([methodstr(SysOperationProgress,New), 0, 4]);
    SendBase::progress([methodstr(SysOperationProgress,Update), id, 0, 'Building messages..']);
    SendBase::progress([methodstr(SysOperationProgress,Update), id, 1, 'Attaching document..']);
    ..
    }

    Finally a snip of my progress callback showing the basic idea.  Note the use of getThisThread() to identify that the code is off-thread, and the call to executeInUIThread() to get back to the UI thread by calling the same method.

    public client static container progress(container args) // [SysOperationProgress method, int id, int num, str text]
    {
    str method;
    int id;
    int num;
    str text;
    str owner = classstr(SendBase);
    SysGlobalCache cache;
    SysOperationProgressEmbedded progress;
    ;

    if (Thread::getThisThread())
    {
    return Thread::executeInUIThread(classnum(SendBase), staticmethodstr(SendBase,Progress), args);
    }
    else
    {
    [method, id, num, text] = args;

    cache = infolog.globalCache();

    switch (method)
    {
    case methodstr(SysOperationProgress,New):
    {
    progress = SendBase::buildProgressForm();
    progress.setTotal(num);
    progress.start();
    for (id = 0; cache.isSet(owner,id); id++) {} // find unused id
    cache.set(owner, id, progress);
    break;
    }
    case methodstr(SysOperationProgress,Update):
    {

    Good luck!

  • Paul Heisterkamp Profile Picture
    1,155 on at

    Hey Brandon,

    First of all thank you for your examples, they helped me allot!

    Your solution worked for my scenario to calculate a container in thread and send the result back to UI.

    So first step resolved...Great!

    But my second scenario is to fill a temp table in thread. The solution of sending contend of the temp table via container from thread to UI is not applicable because there are too many records in the temp table. So I have to pass the instance of temp table to the thread.

    Do you know a way to pass the instance of a temp table? Maybe via temptable.getPhysicalTableName()?

    The only way I found to fill the instance is direct SQL on from getPhysicalTableName() returned table.

    Paul

  • Suggested answer
    Brandon Wiese Profile Picture
    17,788 on at

    Can you not use an AOT table of type TempDb temporary table?  If so, then the table name is a given, but then you want to identify the correct records (as opposed to records possibly inserted by other users at the same time or left over from previous operations).  I would set the Created by transaction to true, and then insert all of your records within a single ttsbegin/ttscommit block, which will guarantee they all share the same transaction Id, which you can send back to the calling form.  This is similar to how SSRS operates with TempDb tables also.

  • Paul Heisterkamp Profile Picture
    1,155 on at

    Yes a have a AOT table of type TempDb but Created by Transaction will not do the trick...

    The following code show up the possibility of linking temptables by using linkPhysicalTableInstance() but in the thread a do not have the instance where I want to link to. So I need the possibility of linking the temptable to a PhysicalTableName or a similar solution :-)

    static void tempDbJob(Args _args)

    {

       TmpInventAge    tmpInventAge;

       str             physicalTableName;

       TmpInventAge    tmpInventAge2;

       str             physicalTableName2;

       TmpInventAge    tmpInventAge3;

       str             physicalTableName3;

       select firstOnly tmpInventAge;

       physicalTableName = tmpInventAge.getPhysicalTableName();

       select firstOnly tmpInventAge2;

       physicalTableName2 = tmpInventAge2.getPhysicalTableName();

       tmpInventAge3.linkPhysicalTableInstance(tmpInventAge);

       select firstOnly tmpInventAge3;

       physicalTableName3 = tmpInventAge3.getPhysicalTableName();

    }

  • Paul Heisterkamp Profile Picture
    1,155 on at

    Hey all,

    Here is my summary.

    1. If you want to calculate a container in a dedicated thread, this will work with Brandon’s solution.

    2. If you want to fill a temp table in a dedicated thread, this is not possible. The only way to do this is to pack the records in the thread and send them back to UI via container. This solution is not applicable if you handle with thousands of records...

    Cheers,

    Paul

Under review

Thank you for your reply! To ensure a great experience for everyone, your content is awaiting approval by our Community Managers. Please check back later.

Helpful resources

Quick Links

Responsible AI policies

As AI tools become more common, we’re introducing a Responsible AI Use…

Neeraj Kumar – Community Spotlight

We are honored to recognize Neeraj Kumar as our Community Spotlight honoree for…

Leaderboard > 🔒一 Microsoft Dynamics AX (Archived)

#1
Martin Dráb Profile Picture

Martin Dráb 4 Most Valuable Professional

#1
Priya_K Profile Picture

Priya_K 4

#3
MyDynamicsNAV Profile Picture

MyDynamicsNAV 2

Last 30 days Overall leaderboard

Featured topics

Product updates

Dynamics 365 release plans