第五章 Caché 变量大全 $HALT 变量
包含暂停陷阱例程调用。
大纲
$HALT
描述
$HALT
包含当前暂停陷阱例程的名称。当遇到HALT
命令时,应用程序将调用暂停陷阱例程。该暂停陷阱例程可以在发出HALT
命令之前执行清理或日志记录处理,或者可以替代其他处理而不是暂停程序执行。
可以使用SET
命令将$HALT
设置为暂停陷阱例程。暂停陷阱例程由带引号的字符串指定,格式如下
SET $HALT=location
此处的位置可以指定为label
(当前例程或过程中的标签),^routine
(指定外部例程的开始)或label^routine
(指定外部例程中的指定标签)。
$HALT
在某些情况下(但在程序中不支持)支持label + offset
。这个可选的+offset
是一个整数,指定要从label
偏移的行数。 InterSystems建议在指定位置时避免使用行偏移量。
调用过程或CACHESYS%
例程时,不能指定+偏移量。如果尝试这样做,Caché会发出<NOLINE>
错误。
$HALT
定义当前上下文的暂停陷阱例程。如果已经为当前上下文定义了停止陷阱,则新陷阱将替换它。如果指定了不存在的例程名称,则HALT
命令将忽略$HALT
并展开堆栈以在先前的上下文级别定位有效的$HALT
。
要删除当前上下文的暂停陷阱,请将$HALT
设置为空字符串。尝试使用NEW
或KILL
命令删除暂停陷阱会导致<SYNTAX>
错误。
暂停陷阱执行
发出HALT
命令时,Caché会在当前上下文中检查$HALT
。如果没有为当前上下文定义$HALT
(或者将其设置为不存在的例程名称或空字符串),则Caché会将堆栈展开到先前的上下文,并在其中查找$HALT
。该过程将一直持续到找到定义的$HALT
或堆栈完全解卷为止。 Caché使用$HALT
的值将执行转移到指定的暂停陷阱例程。暂停陷阱例程在定义$HALT
的上下文中执行。没有设置错误代码或发出错误消息。
如果在当前上下文或先前的上下文中未设置有效的$HALT
,则发出HALT
命令将完全展开堆栈并执行实际的程序暂停。
通常,暂停陷阱例程执行一些清理或报告处理,然后发出HALT
命令。请注意,在定义了$HALT
的情况下,原始的HALT
命令将调用暂停陷阱,但不会执行实际的程序暂停。为了使实际停止,停止陷阱例程必须包含第二个HALT
命令。
暂停陷阱例程发出的HALT
命令不会被该暂停陷阱捕获,但是可能会被在较低上下文级别建立的暂停陷阱捕获。因此,可以由单个HALT
命令调用一系列级联的停止陷阱。
$HALT 与 ^%ZSTOP
如果设置了$HALT
,并且在发出HALT
时为^%ZSTOP
定义了代码,则首先执行$HALT
。$HALT
可以防止进程终止,如果它的HALT
陷阱例程不包含HALT
命令。
当进程实际终止时,执行^%ZSTOP
例程。
示例
以下示例使用$HALT
来建立一个HALT陷阱:
/// d ##class(PHA.TEST.SpecialVariables).HALT()
ClassMethod HALT()
{
SET $HALT="CleanupRoutine"
WRITE !,"the halt trap is: ",$HALT
CleanupRoutine
w 1
}
DHC-APP>d ##class(PHA.TEST.SpecialVariables).HALT()
the halt trap is: +101^PHA.TEST.SpecialVariables.11
请注意,终端确保指定的例程存在。
以下示例显示了在定义$HALT
的上下文中如何执行暂停陷阱例程。在此示例中,$HALT
定义为$ESTACK
级别0,HALT
发出为$ESTACK
级别1,并且暂停陷阱例程以$ESTACK
级别0执行。
/// d ##class(PHA.TEST.SpecialVariables).HALT1()
ClassMethod HALT1()
{
Main
NEW $ESTACK
SET $HALT="OnHalt"
WRITE !,"Main $ESTACK= ",$ESTACK," $HALT= ",$HALT // 0
DO SubA
WRITE !,"Returned from SubA" // not executed
QUIT
SubA
WRITE !,"SubA $ESTACK= ",$ESTACK," $HALT= ",$HALT // 1
HALT
WRITE !,"this should never display"
QUIT
OnHalt
WRITE !,"OnHalt $ESTACK= ",$ESTACK // 0
HALT
QUIT
}
image.png
除了$HALT
是在$ESTACK
级别1定义的,以下示例与上一示例相同。在$ESTACK
级别1发出的HALT
命令以及在$ESTACK
级别1执行的暂停陷阱例程。暂停陷阱例程解开堆栈,并且,如果找不到在先前上下文级别定义的$HALT
,它将暂停程序执行。因此,不执行DO
命令之后的WRITE
命令。
/// d ##class(PHA.TEST.SpecialVariables).HALT2()
ClassMethod HALT2()
{
Main
NEW $ESTACK
WRITE !,"Main $ESTACK= ",$ESTACK," $HALT= ",$HALT // 0
DO SubA
WRITE !,"Returned from SubA" // not executed
QUIT
SubA
SET $HALT="OnHalt"
WRITE !,"SubA $ESTACK= ",$ESTACK," $HALT= ",$HALT // 1
HALT
WRITE !,"this should never display"
QUIT
OnHalt
WRITE !,"OnHalt $ESTACK= ",$ESTACK // 1
HALT
QUIT
}
image.png
以下示例显示了如何调用一系列级联的暂停陷阱。暂停陷阱Halt0
定义为$ESTACK
级别0,并且暂停陷阱Halt1
定义为$ESTACK
级别1。HALT
命令以$ESTACK
级别2发出。Caché展开堆栈以在$ESTACK
级别1调用暂停陷阱Halt1
。该停止陷阱发出一个HALT
命令。 Caché展开堆栈以在$ESTACK
级别0调用暂停陷阱Halt0
。此暂停陷阱发出一个HALT
命令,该命令暂停程序执行。
/// d ##class(PHA.TEST.SpecialVariables).HALT3()
ClassMethod HALT3()
{
Main
NEW $ESTACK
SET $HALT="Halt0"
WRITE !,"Main $ESTACK= ",$ESTACK," $HALT= ",$HALT // 0
DO SubA
WRITE !,"Returned from SubA" // not executed
QUIT
SubA
SET $HALT="Halt1"
WRITE !,"SubA $ESTACK= ",$ESTACK," $HALT= ",$HALT // 1
DO SubB
WRITE !,"Returned from SubA" // not executed
QUIT
SubB
WRITE !,"SubB $ESTACK= ",$ESTACK," $HALT= ",$HALT // 2
HALT
WRITE !,"this should never display"
QUIT
Halt0
WRITE !,"Halt0 $ESTACK= ",$ESTACK // 0
WRITE !,"Bye-bye!"
HALT
QUIT
Halt1
WRITE !,"Halt1 $ESTACK= ",$ESTACK // 1
HALT
QUIT
}
image.png
网友评论