实际项目实施过程中,我们会遇到程序性能优化的问题,这里介绍一种方法:通过RFC接口进行远程函数的异步调用实现程序的并行处理。
同步/异步调用函数语法
同步调用:CALL FUNCTION ‘AAA’ ;
同步调用的实质:程序进行单线程执行。
异步调用:CALL FUNCTION ‘AAA’ STARTING NEWTASK “任务名称
DESTINATION IN GROUP
                     PERFORMING <subroutine>ON END OF TASK。"子程序
异步调用的实质:程序进行多线程执行。
一些关于函数异步调用实现程序并行处理的文章,没有介绍如下问题:
⒈ 为了避免相同程序重复运行产生的后台任务相互冲突,需要保证在相同时间段同一程序只被一个用户占用;
⒉ 异步调用获取的最终结果数据与同步调用获取的结果存在差异;
⒊ 固定RFC Server Group如system = ‘parallel_generators’,无法保证程序在不同服务器中通用性。
问题1分析:从MD01中运行MRP我们可以知道,系统为了避免相同程序并发执行,导致后台任务冲突, MD01在并行模式下是不允许被两个用户同时执行的。如下图
    
   
解决方法:通过在程序中利用锁对象来达到程序相同时间段只被同一用户占用的目的。
问题2分析:在LOOP循环中采用异步调用函数的模式,通过SY-SUBRC = 0来判断任务启动成功,当SY-SUBRC <> 0时,则获取先前启动的进程返回的值,但是这样就遇到一个问题:如第N次循环正好分配给程序的进程被占用完,这样本次无法启动一个任务进程,导致本次的原始数据通过函数无法获取目标,从而最终结果出现数据不完整和数值不断变化的现象。
解决方法:牺牲部分性能保证数据的完整。通过RZ12获取服务器的Max. requests in queue 的值,LOOP循环的时候统计启动的启动的进程数是否 = Max. requests inqueue,如果等于则获取先前启动的进程返回的值,然后再重新启动进程,重复此操作。系统分配给每个程序的最大进程数> Max. requests in queue,但是把启动的进程数限制在Max.requests in queue的水平可以保证获取结果的完整性。如下图所示
    
   
问题3分析:一般系统直接指定 =’ parallel_generators ‘,如上图的“服务器组”对应的内容,为了保持一般性通过如下逻辑段获取
    CALL ‘C_SAPGPARAM’ “#EC CI_CCALL ID ‘NAME’ FIELD ‘rdisp/myname’
    
    ID ‘VALUE’ FIELD g_applserver. ”
    
    SELECT SINGLE classname
    
    FROM rzllitab
    
    INTO g_classname “Server Group Name
    
    WHERE applserver = g_applserver
    
    AND grouptype = ‘S’. “S:服务器组,空:登陆组
   
下面通过例子来说明函数异步调用,这里使用函数
‘MD_STOCK_REQUIREMENTS_LIST_API’获取MD04中的物料+工厂 MRP数据明细。首先我们使用同步调用的方法,然后再使用异步调用的方法,比较二者在同等条件下的执行效率。
    (假设需求:从物料工厂表MARC中获取一定的行项目,这里设定为18000条,然后通过调用函数获取物料工厂对应的MRP清单,将物料工厂与获取的对应清单整合输出)
    
    同步调用:(完整程序在程序最后)
   
select matnr werks
UP TO 18000 ROWS               "数据条目18000
INTO CORRESPONDING FIELDS OF TABLE it_marc
FROM marc
WHERE matnr IN s_matnr
AND   werks IN s_werks.
    LOOP AT it_marc INTO wa_marc.
    
    CLEAR it_md.
    
    CALL FUNCTION ‘MD_STOCK_REQUIREMENTS_LIST_API’
    
    EXPORTING
    
    MATNR = wa_marc-matnr
    
    WERKS = wa_marc-werks
    
    TABLES
    
    MDEZX = it_md
    
    EXCEPTIONS
    
    MATERIAL_PLANT_NOT_FOUND = 1
    
    PLANT_NOT_FOUND = 2
    
    OTHERS = 3.
   
LOOP AT it_md INTO wa_md.
  MOVE-CORRESPONDING wa_md TO wa_output.
  wa_output-matnr = wa_marc-matnr.
  wa_output-werks = wa_marc-werks.
  APPEND wa_output TO it_output.
  CLEAR:wa_output,wa_md.
ENDLOOP.
CLEAR wa_marc.
    ENDLOOP.
    
    很显然在同步执行情况下,只有一个进程是执行我们调用的函数,其他的进程处于idle状态。
   
异步调用:
解决问题1:为了达到当前用户可以独占程序,进入选择界面即锁定程序:
    AT SELECTION-SCREEN.
    
    “锁定程序
    
    CALL FUNCTION ‘ENQUEUE_EZZSOPR0032’
    
    EXPORTING
    
    mode_trdir = ‘E’ “锁类型
    
    name = ‘ZSOPR0032’ “锁对象名称
    
    x_name = ’ ’
    
    _scope = ‘2’
    
    _wait = ’ ’
    
    _collect = ’ ’
    
    EXCEPTIONS
    
    foreign_lock = 1
    
    system_failure = 2
    
    OTHERS = 3.
    
    IF sy-subrc <> 0.
    
    MESSAGE ‘对象已被锁定,请稍后执行’ TYPE ‘E’.
    
    ENDIF.
    
    解决问题1:当程序异步调用函数的操作结束后,即可接触对程序的锁定:
   
    END OF SELECTION.
    
    “解除程序的锁定
    
    CALL FUNCTION ‘DEQUEUE_EZZSOPR0032’
    
    EXPORTING
    
    mode_trdir = ‘E’
    
    name = ‘ZSOPR0032’
    
    x_name = ’ ’
    
    _scope = ‘3’
    
    _synchron = ’ ’
    
    _collect = ’ ‘.
   
解决问题3:获取RFC Serve Group name
- 
获取 RFC Serve Group name Start–* 
- 
一般系统默认g_classname = ‘parallel_generators’,但为了通用性按照如下方法获取 
 
 CALL ‘C_SAPGPARAM’ “#EC CI_CCALL
 
 ID ‘NAME’ FIELD ‘rdisp/myname’
 
 ID ‘VALUE’ FIELD g_applserver.SELECT SINGLE classname 
 
 FROM rzllitab
 
 INTO g_classname “Server Group Name
 
 WHERE applserver = g_applserver
 
 AND grouptype = ‘S’. “S:服务器组,空:登陆组
- 
获取 RFC Serve Group name End–* 
解决问题2:通过 最大请求队列的值 来控制启动进程数
SELECT matnr werks
UP TO 18000 ROWS               "数据条目18000
INTO CORRESPONDING FIELDS OF TABLE it_marc
FROM marc
WHERE matnr IN s_matnr
AND werks IN s_werks.
LOOP AT it_marc INTO wa_marc.
- 
生成任务名称 = ‘Task’ + sy-tabix Start–* WRITE sy-tabix TO g_taskname. CONDENSE g_taskname. CONCATENATE ‘Task’ g_taskname INTO g_taskname. 
- 
生成任务名称 = ‘Task’ + sy-tabix End–* lw_marc-taskname = g_taskname. lw_marc-matnr = wa_marc-matnr. lw_marc-werks = wa_marc-werks. APPEND wa_marc TO lt_marc. 
- 
异步调用函数 Start–* CALL FUNCTION ‘MD_STOCK_REQUIREMENTS_LIST_API’ STARTINGNEW TASK g_taskname DESTINATION INGROUPg_classname PERFORMING frm_subroutine_done ONEND OF TASK"子程序
- 
只要将函数的EXPORTING参数放在此处,其他参数放到子程序中 EXPORTING matnr = wa_marc-matnr werks = wa_marc-werks
- 
系统标准报错信息 EXCEPTIONS communication_failure = 1 MESSAGE mess system_failure = 2 MESSAGE mess resource_failure = 3. IF sy-subrc = 0. snd_jobs = snd_jobs + 1. ENDIF.
- 
异步调用函数 End–* open_task_num = open_task_num + 1. “记录启动的进程数量 IF open_task_num = p_wp. “p_wp = RZ12中的 Max. requests in queue 
- 
获取并发进程返回的结果 WAIT UNTIL rcv_jobs >= snd_jobs. CLEAR:open_task_num,rcv_jobs,snd_jobs. FREE:lt_marc. 
ENDIF.
CLEAR wa_marc.
ENDLOOP.
    
     &———————————————————————
    
   
*& Form FRM_SUBROUTINE_DONE
    
     &———————————————————————
    
   
FORM frm_subroutine_done USING g_taskname.
rcv_jobs = rcv_jobs + 1. “Receiving data
CLEAR:it_md[].
RECEIVE RESULTS FROMFUNCTION ‘MD_STOCK_REQUIREMENTS_LIST_API’
 TABLES
   mdezx                    = it_md
 EXCEPTIONS
   material_plant_not_found = 1
   plant_not_found          = 2
   OTHERS                   = 3.
functioncall1 = done.
SORT lt_marc BY taskname.
LOOP AT it_md INTO wa_md.
READ TABLE lt_marc INTO lw_marc WITH KEY taskname = g_taskname BINARYSEARCH.
MOVE-CORRESPONDING wa_md TO wa_output.
wa_output-matnr = lw_marc-matnr.
wa_output-werks = lw_marc-werks.
APPEND wa_output TO it_output.
CLEAR:wa_output,wa_md,lw_marc.
ENDLOOP.
ENDFORM. ” FRM_SUBROUTINE_DONE
                                                                        同步调用运行时间
    异步调用运行时间
    
    
    
    
   
SE30中截取的两张运行时间图,
同步用时429s = 83sABAP程序使用时间 + 346s数据访问消耗时间;
异步用时75s = 74sABAP 程序使用时间 + <1s的数据库访问消耗时间。
本服务器Max.requests in queue = 5. 运行时间429 / 75 = 5.7,即提升了5倍多的执行效率。
同步调用完整程序:
福大
Description: 同步调用函数获取MRP明细列表DEMO
    
     &———————————————————————
    
    
    *& 程序名称:同步调用函数获取MRP明细列表DEMO
    
    *& 程 序 名:ZDEMO_MXQ_TB
    
    *& 开发日期:2013-05-15
    
    *& 创 建 者:汉得
    
    *& 申 请 者:
    
    
     &———————————————————————
    
    
    *& 摘要说明
    
    
     &——–
    
    
    *& 从物料工厂表MARC中获取一定的行项目,然后通过调用函数获取物料工厂对应的
    
    *& MRP清单,将物料工厂与获取的对应清单整合输出
    
    
     &———————————————————————
    
    
    *& 变更记录
    
    *& 日期 修改者 传输请求号 修改内容及原因
    
    
     &————— ———- ——————– ——————
    
    
    *
    
    
     &———————————————————————
    
   
REPORT ZDEMO_MXQ_TB.
    
     ———————————————————————-
    
   
- 
Type-pools *
    
     ———————————————————————-
    
    
    TYPE-POOLS: slis.
   
    
     ———————————————————————-
    
   
- 
Table *
    
     ———————————————————————-
    
    
    TABLES:marc.
   
    
     ———————————————————————-
    
   
- 
Internal Tables and Work Areas
    
     ———————————————————————-
    
   
    DATA:BEGIN OF wa_marc,
    
    matnr TYPE marc-matnr, “物料号
    
    werks TYPE marc-werks, “工厂
    
    END OF wa_marc.
   
DATA:it_marc LIKE TABLE OF wa_marc.
    “函数调用参数
    
    DATA:it_md TYPE STANDARD TABLE OF mdez,
    
    wa_md LIKE LINE OF it_md.
   
    DATA:BEGIN OF wa_output.
    
    INCLUDE STRUCTURE mdez.
    
    DATA:matnr TYPE marc-matnr. “物料号
    
    DATA:werks TYPE marc-werks. “工厂
    
    DATA:END OF wa_output.
   
DATA:it_output LIKE TABLE OF wa_output.
    
     ———————————————————————-
    
   
- 
Variables
    
     ———————————————————————-
    
   
    
     ———————————————————————-
    
   
- 
ALV层级关系定义
    
     ———————————————————————-
    
    
    DATA: it_fieldcat TYPE slis_t_fieldcat_alv,
    
    wa_layout TYPE slis_layout_alv.
    
    DATA: wa_fieldcat TYPE slis_fieldcat_alv.
    
    DATA gv_grid TYPE REF TO cl_gui_alv_grid.
   
    DATA: git_events TYPE slis_t_event, “ALV 事件
    
    git_listheader TYPE slis_t_listheader. “ALV 表头
   
DATA wa_header TYPE slis_listheader.
    
     &———————————————————————
    
    
    *& Define marco
    
    
     &———————————————————————
    
    
    DEFINE macro_fill_fcat.
   
clear wa_fieldcat.
    &1 = &1 + 1.
    
    wa_fieldcat-col_pos = &1.
    
    wa_fieldcat-fieldname = &2.
    
    wa_fieldcat-seltext_l = &3.
    
    wa_fieldcat-seltext_m = &3.
    
    wa_fieldcat-seltext_s = &3.
   
append wa_fieldcat to it_fieldcat.
END-OF-DEFINITION.
    
     ———————————————————————-
    
   
- 
SELECTION-SCREEN
    
     ———————————————————————-
    
    
    SELECTION-SCREEN BEGIN OF BLOCK blk1 WITH FRAME TITLE text-001.
    
    *PARAMETERS:p_wp TYPE c . “进程数
    
    SELECT-OPTIONS:s_matnr FOR marc-matnr,
    
    s_werks FOR marc-werks.
   
SELECTION-SCREEN END OF BLOCK blk1.
    *initialialization
    
    INITIALIZATION.
   
    *at selection screen
    
    AT SELECTION-SCREEN.
   
    *start of selection
    
    START-OF-SELECTION.
   
    CALL FUNCTION ‘SAPGUI_PROGRESS_INDICATOR’
    
    EXPORTING
    
    PERCENTAGE = 10
    
    TEXT = ‘数据获取中…’.
   
PERFORM frm_get_date.
    *END OF SELECTION
    
    END-OF-SELECTION.
    
    PERFORM frm_init_fieldcat.
    
    PERFORM frm_init_layout.
    
    PERFORM frm_alv_output.
   
    
     &———————————————————————
    
    
    *& Form FRM_GET_DATE
    
    
     &———————————————————————
    
   
- 
text
    
     ———————————————————————-
    
   
- –> p1 text
- 
     <– p2 text
 
 
 ———————————————————————-
 
 
 FORM FRM_GET_DATE .
    SELECT matnr werks
    
    UP TO 18000 ROWS “最多获取20条数据
    
    INTO CORRESPONDING FIELDS OF TABLE it_marc
    
    FROM marc
    
    WHERE matnr IN s_matnr
    
    AND werks IN s_werks.
   
LOOP AT it_marc INTO wa_marc.
CLEAR it_md.
CALL FUNCTION 'MD_STOCK_REQUIREMENTS_LIST_API'
  EXPORTING
    MATNR                    = wa_marc-matnr
    WERKS                    = wa_marc-werks
  TABLES
    MDEZX                    = it_md
  EXCEPTIONS
    MATERIAL_PLANT_NOT_FOUND = 1
    PLANT_NOT_FOUND          = 2
    OTHERS                   = 3.
LOOP AT it_md INTO wa_md.
  MOVE-CORRESPONDING wa_md TO wa_output.
  wa_output-matnr = wa_marc-matnr.
  wa_output-werks = wa_marc-werks.
  APPEND wa_output TO it_output.
  CLEAR:wa_output,wa_md.
ENDLOOP.
CLEAR wa_marc.
ENDLOOP.
ENDFORM. ” FRM_GET_DATE
    
     &———————————————————————
    
    
    *& Form FRM_INIT_FIELDCAT
    
    
     &———————————————————————
    
   
- 
text
    
     ———————————————————————-
    
   
- –> p1 text
- 
     <– p2 text
 
 
 ———————————————————————-
 
 
 FORM frm_init_fieldcat.
DATA: l_colpos TYPE lvc_s_fcat-col_pos VALUE 0.
    macro_fill_fcat l_colpos ‘MATNR’ ‘物料号’ .
    
    macro_fill_fcat l_colpos ‘WERKS’ ‘工厂’ .
    
    macro_fill_fcat l_colpos ‘DELKZ’ ‘MRP元素’ .
    
    macro_fill_fcat l_colpos ‘MNG01’ ‘数量’ .
    
    macro_fill_fcat l_colpos ‘DAT00’ ‘日期’ .
   
ENDFORM. ” FRM_INIT_FIELDCAT
    
     &———————————————————————
    
    
    *& Form FRM_INIT_LAYOUT
    
    
     &———————————————————————
    
   
- 
text
    
     ———————————————————————-
    
   
- –> p1 text
- 
     <– p2 text
 
 
 ———————————————————————-
 
 
 FORM frm_init_layout .
    wa_layout-zebra = ‘X’.
    
    wa_layout-f2code = ‘&ETA’. “双击显示详细信息
    
    wa_layout-detail_popup = ‘X’.
    
    wa_layout-colwidth_optimize = ‘X’.
   
- wa_layout-box_fieldname = ‘BOX’.”将BOX字段作为选择标记列
    ENDFORM. ” FRM_INIT_LAYOUT
    
    
     &———————————————————————
    
    
    *& Form FRM_ALV_OUTPUT
    
    
     &———————————————————————
    
   
- 
text
    
     ———————————————————————-
    
   
- 
–> p1 text 
- 
<– p2 text 
 
 
 ———————————————————————-
 
 
 FORM frm_alv_output .
 
 CALL FUNCTION ‘REUSE_ALV_GRID_DISPLAY’
 
 EXPORTING
 
 i_callback_program = sy-repid
 
 is_layout = wa_layout
 
 it_fieldcat = it_fieldcat
 
 i_save = ‘A’
- 
it_events = git_events[]
- 
i_callback_pf_status_set = 'PF_STATUS_SET'
- 
i_callback_user_command = 'USER_COMMAND'TABLES 
 
 t_outtab = it_output
 
 EXCEPTIONS
 
 program_error = 1
 
 OTHERS = 2.IF sy-subrc <> 0. 
 
 MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
 
 WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
 
 ENDIF.
 
 ENDFORM. ” FRM_ALV_OUTPUT
    *Selection texts
    
    *———————————————————-
   
- S_MATNR D .
- 
     S_WERKS D .
 
 Extracted by Direct Download Enterprise version 1.3.1 – E.G
异步调用完整程序:
    Code listing for: ZDEMO_MXQ_YB
    
    Description: 异步调用函数获取MRP明细列表DEMO
   
    
     &———————————————————————
    
    
    *& 程序名称:异步调用函数获取MRP明细列表DEMO
    
    *& 程 序 名:ZDEMO_MXQ_YB
    
    *& 开发日期:2013-05-15
    
    *& 创 建 者:汉得
    
    *& 申 请 者:
    
    
     &———————————————————————
    
    
    *& 摘要说明
    
    
     &——–
    
    
    *& 从物料工厂表MARC中获取一定的行项目,然后通过调用函数获取物料工厂对应的
    
    *& MRP清单,将物料工厂与获取的对应清单整合输出
    
    
     &———————————————————————
    
    
    *& 变更记录
    
    *& 日期 修改者 传输请求号 修改内容及原因
    
    
     &————— ———- ——————– ——————
    
    
    *
    
    
     &———————————————————————
    
   
REPORT zdemo_mxq_yb.
    
     ———————————————————————-
    
   
- 
Type-pools *
    
     ———————————————————————-
    
    
    TYPE-POOLS: slis.
   
    
     ———————————————————————-
    
   
- 
Table *
    
     ———————————————————————-
    
    
    TABLES:marc.
   
    
     ———————————————————————-
    
   
- 
Internal Tables and Work Areas
    
     ———————————————————————-
    
   
    DATA:BEGIN OF wa_marc,
    
    matnr TYPE marc-matnr, “物料号
    
    werks TYPE marc-werks, “工厂
    
    taskname(10) TYPE c, “任务名
    
    END OF wa_marc.
   
DATA:it_marc LIKE TABLE OF wa_marc.
    DATA:lt_marc LIKE TABLE OF wa_marc, “存放临时数据
    
    lw_marc LIKE wa_marc.
   
    “函数调用参数
    
    DATA:it_md TYPE STANDARD TABLE OF mdez,
    
    wa_md LIKE LINE OF it_md.
   
    DATA:BEGIN OF wa_output.
    
    INCLUDE STRUCTURE mdez.
    
    DATA:matnr TYPE marc-matnr. “物料号
    
    DATA:werks TYPE marc-werks. “工厂
    
    DATA:END OF wa_output.
   
DATA:it_output LIKE TABLE OF wa_output.
    
     ———————————————————————-
    
   
- 
Variables
    
     ———————————————————————-
    
    
    DATA:g_taskname(10) TYPE c, “task name(同时运行的任务名称必须保持唯一)
    
    g_classname TYPE rzlli_apcl, “Server Group Name
    
    g_applserver TYPE rzllitab-applserver,”RFC Serve Group
    
    excp_flag(1) TYPE c. “Number of RESOURCE_FAILUREs
   
    DATA:snd_jobs TYPE i,
    
    rcv_jobs TYPE i,
    
    functioncall1(1) TYPE c.
   
CONSTANTS: done(1) TYPE c VALUE ‘X’.
    
     ———————————————————————-
    
   
- 
ALV层级关系定义
    
     ———————————————————————-
    
    
    DATA: it_fieldcat TYPE slis_t_fieldcat_alv,
    
    wa_layout TYPE slis_layout_alv.
    
    DATA: wa_fieldcat TYPE slis_fieldcat_alv.
    
    DATA gv_grid TYPE REF TO cl_gui_alv_grid.
   
    DATA: git_events TYPE slis_t_event, “ALV 事件
    
    git_listheader TYPE slis_t_listheader. “ALV 表头
   
DATA wa_header TYPE slis_listheader.
    
     &———————————————————————
    
    
    *& Define marco
    
    
     &———————————————————————
    
    
    DEFINE macro_fill_fcat.
   
clear wa_fieldcat.
    &1 = &1 + 1.
    
    wa_fieldcat-col_pos = &1.
    
    wa_fieldcat-fieldname = &2.
    
    wa_fieldcat-seltext_l = &3.
    
    wa_fieldcat-seltext_m = &3.
    
    wa_fieldcat-seltext_s = &3.
   
append wa_fieldcat to it_fieldcat.
END-OF-DEFINITION.
    
     ———————————————————————-
    
   
- 
SELECTION-SCREEN
    
     ———————————————————————-
    
    
    SELECTION-SCREEN BEGIN OF BLOCK blk1 WITH FRAME TITLE text-001.
    
    *PARAMETERS:p_wp TYPE c . “进程数
    
    SELECT-OPTIONS:s_matnr FOR marc-matnr,
    
    s_werks FOR marc-werks.
   
PARAMETERS:p_wp TYPE c . “并发进程数(根据RZ12中的最大请求队列数设置)
SELECTION-SCREEN END OF BLOCK blk1.
    *initialialization
    
    INITIALIZATION.
    
    p_wp = 5.
   
    *at selection screen
    
    AT SELECTION-SCREEN.
   
    “锁定程序
    
    CALL FUNCTION ‘ENQUEUE_EZZSOPR0032’
    
    EXPORTING
    
    mode_trdir = ‘E’
    
    name = ‘ZSOPR0032’
    
    x_name = ’ ’
    
    _scope = ‘2’
    
    _wait = ’ ’
    
    _collect = ’ ’
    
    EXCEPTIONS
    
    foreign_lock = 1
    
    system_failure = 2
    
    OTHERS = 3.
   
IF sy-subrc <> 0.
- 
     Implement suitable error handling here
 
 MESSAGE ‘对象已被锁定,请稍后执行’ TYPE ‘E’.
 
 ELSE.
 
 “锁定成功
 
 ENDIF.
    *start of selection
    
    START-OF-SELECTION.
   
    CALL FUNCTION ‘SAPGUI_PROGRESS_INDICATOR’
    
    EXPORTING
    
    percentage = 10
    
    text = ‘数据获取中…’.
   
PERFORM frm_get_date.
    *END OF SELECTION
    
    END-OF-SELECTION.
   
    “解除程序的锁定
    
    CALL FUNCTION ‘DEQUEUE_EZZSOPR0032’
    
    EXPORTING
    
    mode_trdir = ‘E’
    
    name = ‘ZSOPR0032’
    
    x_name = ’ ’
    
    _scope = ‘3’
    
    _synchron = ’ ’
    
    _collect = ’ ‘.
   
    PERFORM frm_init_fieldcat.
    
    PERFORM frm_init_layout.
    
    PERFORM frm_alv_output.
   
    
     &———————————————————————
    
    
    *& Form FRM_GET_DATE
    
    
     &———————————————————————
    
   
- 
text
    
     ———————————————————————-
    
   
- –> p1 text
- 
     <– p2 text
 
 
 ———————————————————————-
 
 
 FORM frm_get_date .
DATA:mess(40) TYPE c. “并发执行出错信息
DATA:open_task_num TYPE i. “启动任务数量
    SELECT matnr werks
    
    UP TO 18000 ROWS “”数据条目18000
    
    INTO CORRESPONDING FIELDS OF TABLE it_marc
    
    FROM marc
    
    WHERE matnr IN s_matnr
    
    AND werks IN s_werks.
   
- 
获取 RFC Serve Group name Start–* 
- 
一般系统默认g_classname = ‘parallel_generators’,但为了通用性按照如下方法获取 
 
 CALL ‘C_SAPGPARAM’ “#EC CI_CCALL
 
 ID ‘NAME’ FIELD ‘rdisp/myname’
 
 ID ‘VALUE’ FIELD g_applserver.SELECT SINGLE classname 
 
 FROM rzllitab
 
 INTO g_classname “Server Group Name
 
 WHERE applserver = g_applserver
 
 AND grouptype = ‘S’. “S:服务器组,空:登陆组
- 
获取 RFC Serve Group name End–* 
CLEAR open_task_num.
LOOP AT it_marc INTO wa_marc.
- 
生成任务名称 = ‘Task’ + sy-tabix Start–* 
 
 WRITE sy-tabix TO g_taskname.
 
 CONDENSE g_taskname.
 
 CONCATENATE ‘Task’ g_taskname INTO g_taskname.
- 
生成任务名称 = ‘Task’ + sy-tabix End–* lw_marc-taskname = g_taskname. 
 
 lw_marc-matnr = wa_marc-matnr.
 
 lw_marc-werks = wa_marc-werks.
 
 APPEND wa_marc TO lt_marc.
- 
异步调用函数 Start–* 
 
 CALL FUNCTION ‘MD_STOCK_REQUIREMENTS_LIST_API’ STARTING NEW TASK g_taskname
 
 DESTINATION IN GROUP g_classname
 
 PERFORMING frm_subroutine_done ON END OF TASK “子程序
- 
只要将函数的EXPORTING参数放在此处,其他参数放到子程序中 EXPORTING matnr = wa_marc-matnr werks = wa_marc-werks
- 
系统标准报错信息 EXCEPTIONS communication_failure = 1 MESSAGE mess system_failure = 2 MESSAGE mess resource_failure = 3. IF sy-subrc = 0. snd_jobs = snd_jobs + 1. ENDIF.
- 
异步调用函数 End–* open_task_num = open_task_num + 1. “记录启动的进程数量 IF open_task_num = p_wp. “p_wp = RZ12中的 Max. requests in queue 
- 
获取并发进程返回的结果 WAIT UNTIL rcv_jobs >= snd_jobs. CLEAR:open_task_num,rcv_jobs,snd_jobs. FREE:lt_marc.ENDIF. CLEAR wa_marc. ENDLOOP. 
ENDFORM. ” FRM_GET_DATE
    
     &———————————————————————
    
    
    *& Form FRM_SUBROUTINE_DONE
    
    
     &———————————————————————
    
   
- 
text
    
     ———————————————————————-
    
   
- –> p1 text
- 
     <– p2 text
 
 
 ———————————————————————-
 
 
 FORM frm_subroutine_done USING g_taskname.
rcv_jobs = rcv_jobs + 1. “”Receiving data
    CLEAR:it_md[].
    
    RECEIVE RESULTS FROM FUNCTION ‘MD_STOCK_REQUIREMENTS_LIST_API’
    
    TABLES
    
    mdezx = it_md
    
    EXCEPTIONS
    
    material_plant_not_found = 1
    
    plant_not_found = 2
    
    OTHERS = 3.
   
functioncall1 = done.
SORT lt_marc BY taskname.
    LOOP AT it_md INTO wa_md.
    
    READ TABLE lt_marc INTO lw_marc WITH KEY taskname = g_taskname BINARY SEARCH.
    
    MOVE-CORRESPONDING wa_md TO wa_output.
    
    wa_output-matnr = lw_marc-matnr.
    
    wa_output-werks = lw_marc-werks.
    
    APPEND wa_output TO it_output.
   
CLEAR:wa_output,wa_md,lw_marc.
ENDLOOP.
ENDFORM. ” FRM_SUBROUTINE_DONE
    
     &———————————————————————
    
    
    *& Form FRM_INIT_FIELDCAT
    
    
     &———————————————————————
    
   
- 
text
    
     ———————————————————————-
    
   
- –> p1 text
- 
     <– p2 text
 
 
 ———————————————————————-
 
 
 FORM frm_init_fieldcat.
DATA: l_colpos TYPE lvc_s_fcat-col_pos VALUE 0.
    macro_fill_fcat l_colpos ‘MATNR’ ‘物料号’ .
    
    macro_fill_fcat l_colpos ‘WERKS’ ‘工厂’ .
    
    macro_fill_fcat l_colpos ‘DELKZ’ ‘MRP元素’ .
    
    macro_fill_fcat l_colpos ‘MNG01’ ‘数量’ .
    
    macro_fill_fcat l_colpos ‘DAT00’ ‘日期’ .
   
ENDFORM. ” FRM_INIT_FIELDCAT
    
     &———————————————————————
    
    
    *& Form FRM_INIT_LAYOUT
    
    
     &———————————————————————
    
   
- 
text
    
     ———————————————————————-
    
   
- –> p1 text
- 
     <– p2 text
 
 
 ———————————————————————-
 
 
 FORM frm_init_layout .
    wa_layout-zebra = ‘X’.
    
    wa_layout-f2code = ‘&ETA’. “双击显示详细信息
    
    wa_layout-detail_popup = ‘X’.
    
    wa_layout-colwidth_optimize = ‘X’.
   
- wa_layout-box_fieldname = ‘BOX’.”将BOX字段作为选择标记列
    ENDFORM. ” FRM_INIT_LAYOUT
    
    
     &———————————————————————
    
    
    *& Form FRM_ALV_OUTPUT
    
    
     &———————————————————————
    
   
- 
text
    
     ———————————————————————-
    
   
- 
–> p1 text 
- 
<– p2 text 
 
 
 ———————————————————————-
 
 
 FORM frm_alv_output .
 
 CALL FUNCTION ‘REUSE_ALV_GRID_DISPLAY’
 
 EXPORTING
 
 i_callback_program = sy-repid
 
 is_layout = wa_layout
 
 it_fieldcat = it_fieldcat
 
 i_save = ‘A’
- 
it_events = git_events[]
- 
i_callback_pf_status_set = 'PF_STATUS_SET'
- 
i_callback_user_command = 'USER_COMMAND'TABLES 
 
 t_outtab = it_output
 
 EXCEPTIONS
 
 program_error = 1
 
 OTHERS = 2.IF sy-subrc <> 0. 
 
 MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
 
 WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
 
 ENDIF.
 
 ENDFORM. ” FRM_ALV_OUTPUT
 
 
 
 
 
 *Selection texts
 
 *———————————————————-
- 
P_WP 并发进程数 
- 
S_MATNR D . 
- 
S_WERKS D . 
    *Messages
    
    *———————————————————-
    
    *
   
- Message class: Hard coded
- 对象已被锁定,请稍后执行
 
