SAP ABAP程序优化-多线程并行处理
2013-05-23 10:08
106 查看
转载请标明出处:http://blog.csdn.net/wanglei880526/article/details/8949754
实际项目实施过程中,我们会遇到程序性能优化的问题,这里介绍一种方法:通过RFC接口进行远程函数的异步调用实现程序的并行处理。
同步/异步调用函数语法
同步调用:CALLFUNCTION'AAA';
同步调用的实质:程序进行单线程执行。
异步调用:CALL
FUNCTION'AAA'STARTING
NEWTASK<taskname>"任务名称
DESTINATIONINGROUP<RFCServeGroup>
PERFORMING<subroutine>ONENDOFTASK。"子程序
异步调用的实质:程序进行多线程执行。
一些关于函数异步调用实现程序并行处理的文章,没有介绍如下问题:
⒈为了避免相同程序重复运行产生的后台任务相互冲突,需要保证在相同时间段同一程序只被一个用户占用;
⒉异步调用获取的最终结果数据与同步调用获取的结果存在差异;
⒊固定RFCServerGroup如system='parallel_generators',无法保证程序在不同服务器中通用性。
问题1分析:从MD01中运行MRP我们可以知道,系统为了避免相同程序并发执行,导致后台任务冲突,MD01在并行模式下是不允许被两个用户同时执行的。如下图
解决方法:通过在程序中利用锁对象来达到程序相同时间段只被同一用户占用的目的。
问题2分析:在LOOP循环中采用异步调用函数的模式,通过SY-SUBRC=0来判断任务启动成功,当SY-SUBRC<>0时,则获取先前启动的进程返回的值,但是这样就遇到一个问题:如第N次循环正好分配给程序的进程被占用完,这样本次无法启动一个任务进程,导致本次的原始数据通过函数无法获取目标,从而最终结果出现数据不完整和数值不断变化的现象。
解决方法:牺牲部分性能保证数据的完整。通过RZ12获取服务器的Max.requestsinqueue的值,LOOP循环的时候统计启动的启动的进程数是否=Max.requestsinqueue,如果等于则获取先前启动的进程返回的值,然后再重新启动进程,重复此操作。系统分配给每个程序的最大进程数>Max.requestsinqueue,但是把启动的进程数限制在Max.requestsinqueue的水平可以保证获取结果的完整性。如下图所示
问题3分析:一般系统直接指定<RFCServeGroup>='parallel_generators',如上图的“服务器组”对应的内容,为了保持一般性通过如下逻辑段获取
CALL'C_SAPGPARAM'"#ECCI_CCALLID'NAME'FIELD'rdisp/myname'
ID'VALUE'FIELDg_applserver."
SELECTSINGLEclassname
FROMrzllitab
INTOg_classname"ServerGroupName
WHEREapplserver=g_applserver
ANDgrouptype='S'."S:服务器组,空:登陆组
下面通过例子来说明函数异步调用,这里使用函数
'MD_STOCK_REQUIREMENTS_LIST_API'获取MD04中的物料+工厂MRP数据明细。首先我们使用同步调用的方法,然后再使用异步调用的方法,比较二者在同等条件下的执行效率。
同步调用:(完整程序在程序最后)
selectmatnrwerks
很显然在同步执行情况下,只有一个进程是执行我们调用的函数,其他的进程处于idle状态。
异步调用:
解决问题1:为了达到当前用户可以独占程序,进入选择界面即锁定程序:
解决问题1:当程序异步调用函数的操作结束后,即可接触对程序的锁定:
解决问题3:获取RFCServeGroupname
解决问题2:通过最大请求队列的值来控制启动进程数
SELECTmatnrwerks
LOOPATit_marcINTOwa_marc.
*
生成任务名称='Task'+sy-tabixStart--*
WRITEsy-tabixTOg_taskname.
CONDENSEg_taskname.
CONCATENATE'Task'g_tasknameINTOg_taskname.
*
生成任务名称='Task'+sy-tabixEnd--*
lw_marc-taskname=g_taskname.
lw_marc-matnr=wa_marc-matnr.
lw_marc-werks=wa_marc-werks.
APPENDwa_marcTOlt_marc.
*
异步调用函数Start--*
CALLFUNCTION'MD_STOCK_REQUIREMENTS_LIST_API'STARTINGNEWTASKg_taskname
DESTINATIONINGROUPg_classname
PERFORMINGfrm_subroutine_doneONENDOFTASK"子程序
*
只要将函数的EXPORTING参数放在此处,其他参数放到子程序中
EXPORTING
matnr=wa_marc-matnr
werks=wa_marc-werks
*
系统标准报错信息
EXCEPTIONS
communication_failure=1MESSAGEmess
system_failure=2MESSAGEmess
resource_failure=3.
IFsy-subrc=0.
snd_jobs=snd_jobs+1.
ENDIF.
*
异步调用函数End--*
open_task_num=open_task_num+1."记录启动的进程数量
IFopen_task_num=p_wp."p_wp=RZ12中的Max.requestsinqueue
*
获取并发进程返回的结果
WAITUNTILrcv_jobs>=snd_jobs.
CLEAR:open_task_num,rcv_jobs,snd_jobs.
FREE:lt_marc.
ENDIF.
CLEARwa_marc.
ENDLOOP.
*&---------------------------------------------------------------------*
*&FormFRM_SUBROUTINE_DONE
*&---------------------------------------------------------------------*
FORMfrm_subroutine_doneUSINGg_taskname.
rcv_jobs=rcv_jobs+1."Receivingdata
CLEAR:it_md[].
RECEIVERESULTSFROMFUNCTION
'MD_STOCK_REQUIREMENTS_LIST_API'
TABLES
mdezx=it_md
EXCEPTIONS
material_plant_not_found=1
plant_not_found=2
OTHERS=3.
functioncall1=done.
SORTlt_marcBYtaskname.
LOOPATit_mdINTOwa_md.
READTABLElt_marcINTOlw_marcWITHKEYtaskname=g_tasknameBINARYSEARCH.
MOVE-CORRESPONDINGwa_mdTOwa_output.
wa_output-matnr=lw_marc-matnr.
wa_output-werks=lw_marc-werks.
APPENDwa_outputTOit_output.
CLEAR:wa_output,wa_md,lw_marc.
ENDLOOP.
ENDFORM."FRM_SUBROUTINE_DONE
同步调用运行时间
异步调用运行时间
SE30中截取的两张运行时间图,
同步用时429s=83sABAP程序使用时间+346s数据访问消耗时间;
异步用时75s=74sABAP程序使用时间+<1s的数据库访问消耗时间。
本服务器Max.requestsinqueue=5.运行时间429/75=5.7,即提升了5倍多的执行效率。
同步调用完整程序:
福大
Description:同步调用函数获取MRP明细列表DEMO
ExtractedbyDirectDownloadEnterpriseversion1.3.1-E.G
异步调用完整程序:
Codelistingfor:ZDEMO_MXQ_YB
Description:异步调用函数获取MRP明细列表DEMO
实际项目实施过程中,我们会遇到程序性能优化的问题,这里介绍一种方法:通过RFC接口进行远程函数的异步调用实现程序的并行处理。
同步/异步调用函数语法
同步调用:CALLFUNCTION'AAA';
同步调用的实质:程序进行单线程执行。
异步调用:CALL
FUNCTION'AAA'STARTING
NEWTASK<taskname>"任务名称
DESTINATIONINGROUP<RFCServeGroup>
PERFORMING<subroutine>ONENDOFTASK。"子程序
异步调用的实质:程序进行多线程执行。
一些关于函数异步调用实现程序并行处理的文章,没有介绍如下问题:
⒈为了避免相同程序重复运行产生的后台任务相互冲突,需要保证在相同时间段同一程序只被一个用户占用;
⒉异步调用获取的最终结果数据与同步调用获取的结果存在差异;
⒊固定RFCServerGroup如system='parallel_generators',无法保证程序在不同服务器中通用性。
问题1分析:从MD01中运行MRP我们可以知道,系统为了避免相同程序并发执行,导致后台任务冲突,MD01在并行模式下是不允许被两个用户同时执行的。如下图
解决方法:通过在程序中利用锁对象来达到程序相同时间段只被同一用户占用的目的。
问题2分析:在LOOP循环中采用异步调用函数的模式,通过SY-SUBRC=0来判断任务启动成功,当SY-SUBRC<>0时,则获取先前启动的进程返回的值,但是这样就遇到一个问题:如第N次循环正好分配给程序的进程被占用完,这样本次无法启动一个任务进程,导致本次的原始数据通过函数无法获取目标,从而最终结果出现数据不完整和数值不断变化的现象。
解决方法:牺牲部分性能保证数据的完整。通过RZ12获取服务器的Max.requestsinqueue的值,LOOP循环的时候统计启动的启动的进程数是否=Max.requestsinqueue,如果等于则获取先前启动的进程返回的值,然后再重新启动进程,重复此操作。系统分配给每个程序的最大进程数>Max.requestsinqueue,但是把启动的进程数限制在Max.requestsinqueue的水平可以保证获取结果的完整性。如下图所示
问题3分析:一般系统直接指定<RFCServeGroup>='parallel_generators',如上图的“服务器组”对应的内容,为了保持一般性通过如下逻辑段获取
CALL'C_SAPGPARAM'"#ECCI_CCALLID'NAME'FIELD'rdisp/myname'
ID'VALUE'FIELDg_applserver."
SELECTSINGLEclassname
FROMrzllitab
INTOg_classname"ServerGroupName
WHEREapplserver=g_applserver
ANDgrouptype='S'."S:服务器组,空:登陆组
下面通过例子来说明函数异步调用,这里使用函数
'MD_STOCK_REQUIREMENTS_LIST_API'获取MD04中的物料+工厂MRP数据明细。首先我们使用同步调用的方法,然后再使用异步调用的方法,比较二者在同等条件下的执行效率。
(假设需求:从物料工厂表MARC中获取一定的行项目,这里设定为18000条,然后通过调用函数获取物料工厂对应的MRP清单,将物料工厂与获取的对应清单整合输出)
同步调用:(完整程序在程序最后)
selectmatnrwerks
UPTO18000ROWS"数据条目18000
INTOCORRESPONDINGFIELDSOFTABLEit_marc
FROMmarc
WHEREmatnrINs_matnr
ANDwerksINs_werks.
LOOPATit_marcINTOwa_marc.
CLEARit_md.
CALLFUNCTION'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.
LOOPATit_mdINTOwa_md.
MOVE-CORRESPONDINGwa_mdTOwa_output.
wa_output-matnr=wa_marc-matnr.
wa_output-werks=wa_marc-werks.
APPENDwa_outputTOit_output.
CLEAR:wa_output,wa_md.
ENDLOOP.
CLEARwa_marc.
ENDLOOP.
很显然在同步执行情况下,只有一个进程是执行我们调用的函数,其他的进程处于idle状态。
异步调用:
解决问题1:为了达到当前用户可以独占程序,进入选择界面即锁定程序:
ATSELECTION-SCREEN.
"锁定程序
CALLFUNCTION'ENQUEUE_EZZSOPR0032'
EXPORTING
mode_trdir='E'"锁类型
name='ZSOPR0032'"锁对象名称
x_name=''
_scope='2'
_wait=''
_collect=''
EXCEPTIONS
foreign_lock=1
system_failure=2
OTHERS=3.
IFsy-subrc<>0.
MESSAGE'对象已被锁定,请稍后执行'TYPE'E'.
ENDIF.
解决问题1:当程序异步调用函数的操作结束后,即可接触对程序的锁定:
ENDOFSELECTION.
"解除程序的锁定
CALLFUNCTION'DEQUEUE_EZZSOPR0032'
EXPORTING
mode_trdir='E'
name='ZSOPR0032'
x_name=''
_scope='3'
_synchron=''
_collect=''.
解决问题3:获取RFCServeGroupname
*获取RFCServeGroupnameStart--*
*一般系统默认g_classname='parallel_generators',但为了通用性按照如下方法获取
CALL'C_SAPGPARAM'"#ECCI_CCALL
ID'NAME'FIELD'rdisp/myname'
ID'VALUE'FIELDg_applserver.
SELECTSINGLEclassname
FROMrzllitab
INTOg_classname"ServerGroupName
WHEREapplserver=g_applserver
ANDgrouptype='S'."S:服务器组,空:登陆组
*获取RFCServeGroupnameEnd--*
解决问题2:通过最大请求队列的值来控制启动进程数
SELECTmatnrwerks
UPTO18000ROWS"数据条目18000
INTOCORRESPONDINGFIELDSOFTABLEit_marc
FROMmarc
WHEREmatnrINs_matnr
ANDwerksINs_werks.
LOOPATit_marcINTOwa_marc.
*
生成任务名称='Task'+sy-tabixStart--*
WRITEsy-tabixTOg_taskname.
CONDENSEg_taskname.
CONCATENATE'Task'g_tasknameINTOg_taskname.
*
生成任务名称='Task'+sy-tabixEnd--*
lw_marc-taskname=g_taskname.
lw_marc-matnr=wa_marc-matnr.
lw_marc-werks=wa_marc-werks.
APPENDwa_marcTOlt_marc.
*
异步调用函数Start--*
CALLFUNCTION'MD_STOCK_REQUIREMENTS_LIST_API'STARTINGNEWTASKg_taskname
DESTINATIONINGROUPg_classname
PERFORMINGfrm_subroutine_doneONENDOFTASK"子程序
*
只要将函数的EXPORTING参数放在此处,其他参数放到子程序中
EXPORTING
matnr=wa_marc-matnr
werks=wa_marc-werks
*
系统标准报错信息
EXCEPTIONS
communication_failure=1MESSAGEmess
system_failure=2MESSAGEmess
resource_failure=3.
IFsy-subrc=0.
snd_jobs=snd_jobs+1.
ENDIF.
*
异步调用函数End--*
open_task_num=open_task_num+1."记录启动的进程数量
IFopen_task_num=p_wp."p_wp=RZ12中的Max.requestsinqueue
*
获取并发进程返回的结果
WAITUNTILrcv_jobs>=snd_jobs.
CLEAR:open_task_num,rcv_jobs,snd_jobs.
FREE:lt_marc.
ENDIF.
CLEARwa_marc.
ENDLOOP.
*&---------------------------------------------------------------------*
*&FormFRM_SUBROUTINE_DONE
*&---------------------------------------------------------------------*
FORMfrm_subroutine_doneUSINGg_taskname.
rcv_jobs=rcv_jobs+1."Receivingdata
CLEAR:it_md[].
RECEIVERESULTSFROMFUNCTION
'MD_STOCK_REQUIREMENTS_LIST_API'
TABLES
mdezx=it_md
EXCEPTIONS
material_plant_not_found=1
plant_not_found=2
OTHERS=3.
functioncall1=done.
SORTlt_marcBYtaskname.
LOOPATit_mdINTOwa_md.
READTABLElt_marcINTOlw_marcWITHKEYtaskname=g_tasknameBINARYSEARCH.
MOVE-CORRESPONDINGwa_mdTOwa_output.
wa_output-matnr=lw_marc-matnr.
wa_output-werks=lw_marc-werks.
APPENDwa_outputTOit_output.
CLEAR:wa_output,wa_md,lw_marc.
ENDLOOP.
ENDFORM."FRM_SUBROUTINE_DONE
同步调用运行时间
异步调用运行时间
SE30中截取的两张运行时间图,
同步用时429s=83sABAP程序使用时间+346s数据访问消耗时间;
异步用时75s=74sABAP程序使用时间+<1s的数据库访问消耗时间。
本服务器Max.requestsinqueue=5.运行时间429/75=5.7,即提升了5倍多的执行效率。
同步调用完整程序:
福大
Description:同步调用函数获取MRP明细列表DEMO
*&---------------------------------------------------------------------*
*&程序名称:同步调用函数获取MRP明细列表DEMO
*&程序名:ZDEMO_MXQ_TB
*&开发日期:2013-05-15
*&创建者:汉得
*&申请者:
*&---------------------------------------------------------------------*
*&摘要说明
*&--------*
*&从物料工厂表MARC中获取一定的行项目,然后通过调用函数获取物料工厂对应的
*&MRP清单,将物料工厂与获取的对应清单整合输出
*&---------------------------------------------------------------------*
*&变更记录
*&日期修改者传输请求号修改内容及原因
*&---------------------------------------------------------------*
*
*&---------------------------------------------------------------------*
REPORTZDEMO_MXQ_TB.
*----------------------------------------------------------------------*
*Type-pools*
*----------------------------------------------------------------------*
TYPE-POOLS:slis.
*----------------------------------------------------------------------*
*Table*
*----------------------------------------------------------------------*
TABLES:marc.
*----------------------------------------------------------------------*
*InternalTablesandWorkAreas
*----------------------------------------------------------------------*
DATA:BEGINOFwa_marc,
matnrTYPEmarc-matnr,"物料号
werksTYPEmarc-werks,"工厂
ENDOFwa_marc.
DATA:it_marcLIKETABLEOFwa_marc.
"函数调用参数
DATA:it_mdTYPESTANDARDTABLEOFmdez,
wa_mdLIKELINEOFit_md.
DATA:BEGINOFwa_output.
INCLUDESTRUCTUREmdez.
DATA:matnrTYPEmarc-matnr."物料号
DATA:werksTYPEmarc-werks."工厂
DATA:ENDOFwa_output.
DATA:it_outputLIKETABLEOFwa_output.
*----------------------------------------------------------------------*
*Variables
*----------------------------------------------------------------------*
*----------------------------------------------------------------------*
*ALV层级关系定义
*----------------------------------------------------------------------*
DATA:it_fieldcatTYPEslis_t_fieldcat_alv,
wa_layoutTYPEslis_layout_alv.
DATA:wa_fieldcatTYPEslis_fieldcat_alv.
DATAgv_gridTYPEREFTOcl_gui_alv_grid.
DATA:git_eventsTYPEslis_t_event,"ALV事件
git_listheaderTYPEslis_t_listheader."ALV表头
DATAwa_headerTYPEslis_listheader.
*&---------------------------------------------------------------------*
*&Definemarco
*&---------------------------------------------------------------------*
DEFINEmacro_fill_fcat.
clearwa_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.
appendwa_fieldcattoit_fieldcat.
END-OF-DEFINITION.
*----------------------------------------------------------------------*
*SELECTION-SCREEN
*----------------------------------------------------------------------*
SELECTION-SCREENBEGINOFBLOCKblk1WITHFRAMETITLEtext-001.
*PARAMETERS:p_wpTYPEc."进程数
SELECT-OPTIONS:s_matnrFORmarc-matnr,
s_werksFORmarc-werks.
SELECTION-SCREENENDOFBLOCKblk1.
*initialialization
INITIALIZATION.
*atselectionscreen
ATSELECTION-SCREEN.
*startofselection
START-OF-SELECTION.
CALLFUNCTION'SAPGUI_PROGRESS_INDICATOR'
EXPORTING
PERCENTAGE=10
TEXT='数据获取中...'.
PERFORMfrm_get_date.
*ENDOFSELECTION
END-OF-SELECTION.
PERFORMfrm_init_fieldcat.
PERFORMfrm_init_layout.
PERFORMfrm_alv_output.
*&---------------------------------------------------------------------*
*&FormFRM_GET_DATE
*&---------------------------------------------------------------------*
*text
*----------------------------------------------------------------------*
*-->p1text
*<--p2text
*----------------------------------------------------------------------*
FORMFRM_GET_DATE.
SELECTmatnrwerks
UPTO18000ROWS"最多获取20条数据
INTOCORRESPONDINGFIELDSOFTABLEit_marc
FROMmarc
WHEREmatnrINs_matnr
ANDwerksINs_werks.
LOOPATit_marcINTOwa_marc.
CLEARit_md.
CALLFUNCTION'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.
LOOPATit_mdINTOwa_md.
MOVE-CORRESPONDINGwa_mdTOwa_output.
wa_output-matnr=wa_marc-matnr.
wa_output-werks=wa_marc-werks.
APPENDwa_outputTOit_output.
CLEAR:wa_output,wa_md.
ENDLOOP.
CLEARwa_marc.
ENDLOOP.
ENDFORM."FRM_GET_DATE
*&---------------------------------------------------------------------*
*&FormFRM_INIT_FIELDCAT
*&---------------------------------------------------------------------*
*text
*----------------------------------------------------------------------*
*-->p1text
*<--p2text
*----------------------------------------------------------------------*
FORMfrm_init_fieldcat.
DATA:l_colposTYPElvc_s_fcat-col_posVALUE0.
macro_fill_fcatl_colpos'MATNR''物料号'.
macro_fill_fcatl_colpos'WERKS''工厂'.
macro_fill_fcatl_colpos'DELKZ''MRP元素'.
macro_fill_fcatl_colpos'MNG01''数量'.
macro_fill_fcatl_colpos'DAT00''日期'.
ENDFORM."FRM_INIT_FIELDCAT
*&---------------------------------------------------------------------*
*&FormFRM_INIT_LAYOUT
*&---------------------------------------------------------------------*
*text
*----------------------------------------------------------------------*
*-->p1text
*<--p2text
*----------------------------------------------------------------------*
FORMfrm_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
*&---------------------------------------------------------------------*
*&FormFRM_ALV_OUTPUT
*&---------------------------------------------------------------------*
*text
*----------------------------------------------------------------------*
*-->p1text
*<--p2text
*----------------------------------------------------------------------*
FORMfrm_alv_output.
CALLFUNCTION'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.
IFsy-subrc<>0.
MESSAGEIDsy-msgidTYPEsy-msgtyNUMBERsy-msgno
WITHsy-msgv1sy-msgv2sy-msgv3sy-msgv4.
ENDIF.
ENDFORM."FRM_ALV_OUTPUT
*Selectiontexts
*----------------------------------------------------------
*S_MATNRD.
*S_WERKSD.
ExtractedbyDirectDownloadEnterpriseversion1.3.1-E.G
异步调用完整程序:
Codelistingfor:ZDEMO_MXQ_YB
Description:异步调用函数获取MRP明细列表DEMO
*&---------------------------------------------------------------------*
*&程序名称:异步调用函数获取MRP明细列表DEMO
*&程序名:ZDEMO_MXQ_YB
*&开发日期:2013-05-15
*&创建者:汉得
*&申请者:
*&---------------------------------------------------------------------*
*&摘要说明
*&--------*
*&从物料工厂表MARC中获取一定的行项目,然后通过调用函数获取物料工厂对应的
*&MRP清单,将物料工厂与获取的对应清单整合输出
*&---------------------------------------------------------------------*
*&变更记录
*&日期修改者传输请求号修改内容及原因
*&---------------------------------------------------------------*
*
*&---------------------------------------------------------------------*
REPORTzdemo_mxq_yb.
*----------------------------------------------------------------------*
*Type-pools*
*----------------------------------------------------------------------*
TYPE-POOLS:slis.
*----------------------------------------------------------------------*
*Table*
*----------------------------------------------------------------------*
TABLES:marc.
*----------------------------------------------------------------------*
*InternalTablesandWorkAreas
*----------------------------------------------------------------------*
DATA:BEGINOFwa_marc,
matnrTYPEmarc-matnr,"物料号
werksTYPEmarc-werks,"工厂
taskname(10)TYPEc,"任务名
ENDOFwa_marc.
DATA:it_marcLIKETABLEOFwa_marc.
DATA:lt_marcLIKETABLEOFwa_marc,"存放临时数据
lw_marcLIKEwa_marc.
"函数调用参数
DATA:it_mdTYPESTANDARDTABLEOFmdez,
wa_mdLIKELINEOFit_md.
DATA:BEGINOFwa_output.
INCLUDESTRUCTUREmdez.
DATA:matnrTYPEmarc-matnr."物料号
DATA:werksTYPEmarc-werks."工厂
DATA:ENDOFwa_output.
DATA:it_outputLIKETABLEOFwa_output.
*----------------------------------------------------------------------*
*Variables
*----------------------------------------------------------------------*
DATA:g_taskname(10)TYPEc,"taskname(同时运行的任务名称必须保持唯一)
g_classnameTYPErzlli_apcl,"ServerGroupName
g_applserverTYPErzllitab-applserver,"RFCServeGroup
excp_flag(1)TYPEc."NumberofRESOURCE_FAILUREs
DATA:snd_jobsTYPEi,
rcv_jobsTYPEi,
functioncall1(1)TYPEc.
CONSTANTS:done(1)TYPEcVALUE'X'.
*----------------------------------------------------------------------*
*ALV层级关系定义
*----------------------------------------------------------------------*
DATA:it_fieldcatTYPEslis_t_fieldcat_alv,
wa_layoutTYPEslis_layout_alv.
DATA:wa_fieldcatTYPEslis_fieldcat_alv.
DATAgv_gridTYPEREFTOcl_gui_alv_grid.
DATA:git_eventsTYPEslis_t_event,"ALV事件
git_listheaderTYPEslis_t_listheader."ALV表头
DATAwa_headerTYPEslis_listheader.
*&---------------------------------------------------------------------*
*&Definemarco
*&---------------------------------------------------------------------*
DEFINEmacro_fill_fcat.
clearwa_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.
appendwa_fieldcattoit_fieldcat.
END-OF-DEFINITION.
*----------------------------------------------------------------------*
*SELECTION-SCREEN
*----------------------------------------------------------------------*
SELECTION-SCREENBEGINOFBLOCKblk1WITHFRAMETITLEtext-001.
*PARAMETERS:p_wpTYPEc."进程数
SELECT-OPTIONS:s_matnrFORmarc-matnr,
s_werksFORmarc-werks.
PARAMETERS:p_wpTYPEc."并发进程数(根据RZ12中的最大请求队列数设置)
SELECTION-SCREENENDOFBLOCKblk1.
*initialialization
INITIALIZATION.
p_wp=5.
*atselectionscreen
ATSELECTION-SCREEN.
"锁定程序
CALLFUNCTION'ENQUEUE_EZZSOPR0032'
EXPORTING
mode_trdir='E'
name='ZSOPR0032'
x_name=''
_scope='2'
_wait=''
_collect=''
EXCEPTIONS
foreign_lock=1
system_failure=2
OTHERS=3.
IFsy-subrc<>0.
*Implementsuitableerrorhandlinghere
MESSAGE'对象已被锁定,请稍后执行'TYPE'E'.
ELSE.
"锁定成功
ENDIF.
*startofselection
START-OF-SELECTION.
CALLFUNCTION'SAPGUI_PROGRESS_INDICATOR'
EXPORTING
percentage=10
text='数据获取中...'.
PERFORMfrm_get_date.
*ENDOFSELECTION
END-OF-SELECTION.
"解除程序的锁定
CALLFUNCTION'DEQUEUE_EZZSOPR0032'
EXPORTING
mode_trdir='E'
name='ZSOPR0032'
x_name=''
_scope='3'
_synchron=''
_collect=''.
PERFORMfrm_init_fieldcat.
PERFORMfrm_init_layout.
PERFORMfrm_alv_output.
*&---------------------------------------------------------------------*
*&FormFRM_GET_DATE
*&---------------------------------------------------------------------*
*text
*----------------------------------------------------------------------*
*-->p1text
*<--p2text
*----------------------------------------------------------------------*
FORMfrm_get_date.
DATA:mess(40)TYPEc."并发执行出错信息
DATA:open_task_numTYPEi."启动任务数量
SELECTmatnrwerks
UPTO18000ROWS""数据条目18000
INTOCORRESPONDINGFIELDSOFTABLEit_marc
FROMmarc
WHEREmatnrINs_matnr
ANDwerksINs_werks.
*获取RFCServeGroupnameStart--*
*一般系统默认g_classname='parallel_generators',但为了通用性按照如下方法获取
CALL'C_SAPGPARAM'"#ECCI_CCALL
ID'NAME'FIELD'rdisp/myname'
ID'VALUE'FIELDg_applserver.
SELECTSINGLEclassname
FROMrzllitab
INTOg_classname"ServerGroupName
WHEREapplserver=g_applserver
ANDgrouptype='S'."S:服务器组,空:登陆组
*获取RFCServeGroupnameEnd--*
CLEARopen_task_num.
LOOPATit_marcINTOwa_marc.
*生成任务名称='Task'+sy-tabixStart--*
WRITEsy-tabixTOg_taskname.
CONDENSEg_taskname.
CONCATENATE'Task'g_tasknameINTOg_taskname.
*生成任务名称='Task'+sy-tabixEnd--*
lw_marc-taskname=g_taskname.
lw_marc-matnr=wa_marc-matnr.
lw_marc-werks=wa_marc-werks.
APPENDwa_marcTOlt_marc.
*异步调用函数Start--*
CALLFUNCTION'MD_STOCK_REQUIREMENTS_LIST_API'STARTINGNEWTASKg_taskname
DESTINATIONINGROUPg_classname
PERFORMINGfrm_subroutine_doneONENDOFTASK"子程序
*只要将函数的EXPORTING参数放在此处,其他参数放到子程序中
EXPORTING
matnr=wa_marc-matnr
werks=wa_marc-werks
*系统标准报错信息
EXCEPTIONS
communication_failure=1MESSAGEmess
system_failure=2MESSAGEmess
resource_failure=3.
IFsy-subrc=0.
snd_jobs=snd_jobs+1.
ENDIF.
*异步调用函数End--*
open_task_num=open_task_num+1."记录启动的进程数量
IFopen_task_num=p_wp."p_wp=RZ12中的Max.requestsinqueue
*获取并发进程返回的结果
WAITUNTILrcv_jobs>=snd_jobs.
CLEAR:open_task_num,rcv_jobs,snd_jobs.
FREE:lt_marc.
ENDIF.
CLEARwa_marc.
ENDLOOP.
ENDFORM."FRM_GET_DATE
*&---------------------------------------------------------------------*
*&FormFRM_SUBROUTINE_DONE
*&---------------------------------------------------------------------*
*text
*----------------------------------------------------------------------*
*-->p1text
*<--p2text
*----------------------------------------------------------------------*
FORMfrm_subroutine_doneUSINGg_taskname.
rcv_jobs=rcv_jobs+1.""Receivingdata
CLEAR:it_md[].
RECEIVERESULTSFROMFUNCTION'MD_STOCK_REQUIREMENTS_LIST_API'
TABLES
mdezx=it_md
EXCEPTIONS
material_plant_not_found=1
plant_not_found=2
OTHERS=3.
functioncall1=done.
SORTlt_marcBYtaskname.
LOOPATit_mdINTOwa_md.
READTABLElt_marcINTOlw_marcWITHKEYtaskname=g_tasknameBINARYSEARCH.
MOVE-CORRESPONDINGwa_mdTOwa_output.
wa_output-matnr=lw_marc-matnr.
wa_output-werks=lw_marc-werks.
APPENDwa_outputTOit_output.
CLEAR:wa_output,wa_md,lw_marc.
ENDLOOP.
ENDFORM."FRM_SUBROUTINE_DONE
*&---------------------------------------------------------------------*
*&FormFRM_INIT_FIELDCAT
*&---------------------------------------------------------------------*
*text
*----------------------------------------------------------------------*
*-->p1text
*<--p2text
*----------------------------------------------------------------------*
FORMfrm_init_fieldcat.
DATA:l_colposTYPElvc_s_fcat-col_posVALUE0.
macro_fill_fcatl_colpos'MATNR''物料号'.
macro_fill_fcatl_colpos'WERKS''工厂'.
macro_fill_fcatl_colpos'DELKZ''MRP元素'.
macro_fill_fcatl_colpos'MNG01''数量'.
macro_fill_fcatl_colpos'DAT00''日期'.
ENDFORM."FRM_INIT_FIELDCAT
*&---------------------------------------------------------------------*
*&FormFRM_INIT_LAYOUT
*&---------------------------------------------------------------------*
*text
*----------------------------------------------------------------------*
*-->p1text
*<--p2text
*----------------------------------------------------------------------*
FORMfrm_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
*&---------------------------------------------------------------------*
*&FormFRM_ALV_OUTPUT
*&---------------------------------------------------------------------*
*text
*----------------------------------------------------------------------*
*-->p1text
*<--p2text
*----------------------------------------------------------------------*
FORMfrm_alv_output.
CALLFUNCTION'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.
IFsy-subrc<>0.
MESSAGEIDsy-msgidTYPEsy-msgtyNUMBERsy-msgno
WITHsy-msgv1sy-msgv2sy-msgv3sy-msgv4.
ENDIF.
ENDFORM."FRM_ALV_OUTPUT
*Selectiontexts
*----------------------------------------------------------
*P_WP并发进程数
*S_MATNRD.
*S_WERKSD.
*Messages
*----------------------------------------------------------
*
*Messageclass:Hardcoded
*对象已被锁定,请稍后执行
相关文章推荐
- SAP ABAP程序优化-多线程并行处理
- SAP ABAP程序优化-多线程并行处理
- 分享一个基于winForm后台单线程推送多线程并行处理业务的小程序框架
- SAP ABAP程序优化-多线程并行处理
- SAP ABAP程序效率优化 Perfomance Tune
- 分享一个基于winForm后台单线程推送多线程并行处理业务的小程序框架
- Java并行程序基础 --- 多线程及容错性处理
- SAP ABAP程序效率优化 Perfomance Tune
- SAP ABAP程序优化方法
- SAP ABAP程序优化(我也来谈谈程序优化)
- SAP ABAP程序效率优化 Perfomance Tune
- SAP ABAP程序优化方法(搜集自论坛)
- SAP ABAP程序效率优化 Perfomance Tune
- SAP ABAP程序性能优化 2
- SAP ABAP程序优化方法(搜集自论坛)
- SAP ABAP程序优化方法(搜集自论坛)
- SAP ABAP程序性能优化
- SAP ABAP程序性能优化
- SAP ABAP程序优化方法
- 分享一个基于winForm后台单线程推送多线程并行处理业务的小程序框架