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!