D365 FO执行进度显示

对于长时间执行的任务,D365 FO为了通知用户处理的进度,新增了一个进度条显示,如下图所示:
D365 FO执行进度显示

 这个功能在AX2012及之前的版本是没有的,之前的版本是通过SysOperationProgress类来实现进度的显示,这个进度条跟界面的在一个线程,
所以用户点击界面是是没响应的。
D365 FO对于长时间操作启用进度显示集成到了SysOperation框架,当然Runbase框架也支持。
搞不懂为什么AX从2012版本开始就推出了SysOperation,并且推荐使用SysOperation替代RunBase,但是看上去还一直在维护RunBase框架,一些新的特性也加到了Runbase上,不知道是出于念旧还是遗留代码还没移植完。

实现方法
如果想显示进度条,只要覆盖canRunInNewSession,让它返回true就可以了。
具体的实例代码如下:

 1 public class PersonController extends SysOperationServiceController
 2 {
 3     static void main(Args _args)
 4     {
 5         PersonController    controller = new PersonController(
 6                                                 classStr(PersonController), 
 7                                                 methodStr(PersonController, changeAge), 
 8                                                 SysOperationExecutionMode::Synchronous);
 9         
10         controller.startOperation();
11     }
12 
13     public void changeAge(PersonDataContract _contract)
14     {
15         sleep(10000);
16         info (int2Str(_contract.parmAge()));
17     }
18 
19     protected boolean canRunInNewSession()
20     {
21         return true;
22     }
23 
24     public boolean canGoBatch()
25     {
26         return false;
27     }
28 
29     public ClassDescription caption()
30     {
31         return "修改年龄";
32     }
33 
34 }

canGoBatch方法标识当前类是否支持批处理,我这里测试不想让它执行批处理,为了模仿长时间操作,用Sleep停止10S
为了简便起见,没有新创建Services类,正规的做法应该是在创建一个用于修改年龄的Services类供Controller调用,不过这样调用也没什么。
DataContract用于参数传递,定义如下。

[DataContract]
public class PersonDataContract
{   
    
    int age;
    [DataMember,SysOperationLabel("年龄")]
    public int parmAge(int _age = age)
    {
        age = _age;
        return age;
    }
}

执行上述方法就可以显示执行进度了。
实现原理
查看SysOperationServiceController的startOperation方法,不难发现这个进度条实现的原理。
是通过SysOperationSandboxForm这个Form实现的,在Form的init方法里调用了父类FormRun的runAsync方法,把要执行的任务放到另一个线程里执行。
至于显示的执行时间,是通过在窗体SysOperationSandboxForm上添加一个TimerControl控件实现的,具体实现可以查看类FormRun的addTimerForAsyncTaskPolling方法。

上一篇:生成函数


下一篇:差分约束