1. 程式人生 > >SAP ABAP程式優化-多執行緒並行處理

SAP ABAP程式優化-多執行緒並行處理

               

實際專案實施過程中,我們會遇到程式效能優化的問題,這裡介紹一種方法:通過RFC介面進行遠端函式的非同步呼叫實現程式的並行處理。

   同步/非同步呼叫函式語法

同步呼叫:CALL FUNCTION 'AAA' ;

同步呼叫的實質:程式進行單執行緒執行。

非同步呼叫:CALL FUNCTION 'AAA' STARTING NEWTASK <taskname> "任務名稱

DESTINATION IN GROUP <RFC Serve 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分析:一般系統直接指定<RFC Serve Group> =' 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.*initialializationINITIALIZATION.*at selection screenAT SELECTION-SCREEN.*start of selectionSTART-OF-SELECTION.  CALL FUNCTION 'SAPGUI_PROGRESS_INDICATOR'    EXPORTING      PERCENTAGE = 10      TEXT       = '資料獲取中...'.  PERFORM frm_get_date.*END OF SELECTIONEND-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_YBDescription: 非同步呼叫函式獲取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_FAILUREsDATA: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.*initialializationINITIALIZATION.  p_wp = 5.*at selection screenAT 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 selectionSTART-OF-SELECTION.  CALL FUNCTION 'SAPGUI_PROGRESS_INDICATOR'    EXPORTING      percentage = 10      text       = '資料獲取中...'.  PERFORM frm_get_date.*END OF SELECTIONEND-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*   物件已被鎖定,請稍後執行