Statement BEGIN SEQUENCE Foundation
Introduces control structure for BREAK or Break().
The BEGIN SEQUENCE statement introduces a control structure for handling runtime errors.
BEGIN SEQUENCE
<SourceCode>...
[BREAK [<Expression>]]
<SourceCode>...
[RECOVER [USING <VarName>]]
<SourceCode>...
END [SEQUENCE]
The statements BEGIN SEQUENCE and ENDSEQUENCE form a control structure which is used mainly for handling runtime errors. The execution of code between the two statements can be interrupted by a BREAK statement or the Break() function, and the program continues at the next executable line which follows the ENDSEQUENCE statement or the RECOVER statement. When no BREAK is executed within the BEGIN SEQUENCE...END structure, a program continues after the ENDSEQUENCE statement and ignores the RECOVER statement. RECOVER marks a continuation point to which control passes only in the case of a BREAK statement or the Break() function.
The RECOVER statement is used exclusively for the treatment of runtime errors. With the USING option, a value specified with BREAK <Expression> , which is usually an error object, can be assigned to the variable <VarName>. An error object contains information about a runtime error and can be evaluated in the source code following the RECOVER statement.
BEGIN SEQUENCE..RECOVER blocks have the following restrictions: The statements EXIT, LOOP and RETURN cannot be used between BEGIN SEQUENCE and RECOVER, but can be used in the code following the RECOVER statement. That means that program execution between the statements BEGIN SEQUENCE and RECOVER can be interrupted only by the BREAK statement or by the Break() function.
BEGIN SEQUENCE..RECOVER..END is a very powerful control structure for the handling of runtime errors. The statements may be optionally nested to any depth. The BREAK statement can be used for localized error handling specific to the context of the BEGIN SEQUENCE..END code. A special continuation point can be defined with ENDSEQUENCE, at which point a program continues as soon as the BREAK statement is executed. Deeply nested DO WHILE loops, for example, can be exited by a single BREAK statement.
Further information about the treatment of runtime errors can be found in the descriptions of the error object class and the ErrorBlock() function.
Notes for multiple threads The BREAK statement interrupts the program flow of the thread that executes the statement. Therefore BREAK can be issued outside a BEGIN SEQUENCE..END structure when using multiple threads. In this case BREAK terminates the thread when called outside BEGIN SEQUENCE..END. If it is the very first thread, the program ends.
// The example shows the working of a BREAK statement, which
// is executed within a BEGIN SEQUENCE..END construction.
// In the example, three DO WHILE loops are exited at once
// by BREAK. Without the BREAK condition, they would continue
// to run.
PROCEDURE Main
LOCAL i, j
BEGIN SEQUENCE
DO WHILE .T. // continuous loop
i := 0
DO WHILE ++i<=1000 // loop to 1000
j := 0
DO WHILE ++j<=1000 // loop to 1000*1000
@ 0, 0 SAY "i =" + Str(i)
@ 0, Col() SAY "j =" + Str(j)
IF i == 9 .AND. j == 10
BREAK // break after 8010
ENDIF // iterations
ENDDO
ENDDO
ENDDO
ENDSEQUENCE
? "Three DO WHILE loops exited with BREAK "
RETURN
// In the example, the UDF DbfNtxUse() opens a DBF file and its index
// files. The information for creating the index files is passed in an
// array. When an index file does not exist, a runtime error occurs and
// the function Break() branches out of the error block to the RECOVER
// statement and passes an error object to it. After RECOVER, the
// missing index file is created.
#include "Error.ch"
PROCEDURE Main
LOCAL aIndexFiles
aIndexFiles := ;
{ ;
{ "CUSTOMRA", "CUSTNR" }, ;
{ "CUSTOMRB", "Upper(LAST_NAME + FIRST_NAME)" }, ;
{ "CUSTOMRC", "ZIP" } ;
}
DbfNtxUse( "CUSTOMER", aIndexFiles )
RETURN
PROCEDURE DbfNtxUse( cDbfFile, aIndexFiles )
LOCAL n, nMax, bSaveErrorBlock, oError
LOCAL cIndexFile, cIndexKey
USE (cDbfFile) NEW // Open DBF file
n := 1
nMax := Len( aIndexFiles )
DO WHILE n <= nMax
// Define error block
bSaveErrorBlock := ErrorBlock( {|e| Break(e)} )
BEGIN SEQUENCE // Get index data
cIndexFile := aIndexFiles[n,1]
cIndexKey := aIndexFiles[n,2]
OrdListAdd( cIndexFile ) // Open index file
n++
RECOVER USING oError
ErrorBlock(bSaveErrorBlock) // Restore old error code block
// for error handling
IF oError:osCode == 2 // Error: file does not exist
USE (cDbfFile) EXCLUSIVE // open DBF file exclusively
INDEX ON &cIndexKey ; // create index file
TO &cIndexFile
USE (cDbfFile) // Open file SHARED without
// index files
n := 1
LOOP // Back to BEGIN SEQUENCE
ENDIF
ENDSEQUENCE
ErrorBlock(bSaveErrorBlock) // Restore old error code block
ENDDO
RETURN
If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use this form to report a documentation issue.