Earlier versions of Visual Basic did not provide for structured error handling; you were forced to implement unstructured error handling in your programs. Although unstructured error handling is out of favor now, the fact remains that there's a lot of code out there that uses it. For that reason alone, you should at least know how unstructured error handling is implemented.
The On Error Goto Statement
Implementing unstructured error processing is a two-step process. The first step is to activate error handling using the On Error Goto statement. The basic syntax is
On Error Goto LabelName
where LabelName is the Visual Basic .NET program label. Visual Basic .NET program labels follow the same naming rules as variables , but they must end with a colon ( : ).
To illustrate how we might implement unstructured error handling, we'll modify the btnStart Click event from Listing 19.1 to use the On Error Goto statement. The code change is shown in Listing 19.2.
Listing 19.2 Using Unstructured Error Handling with On Error Goto
Private Sub btnStart_Click(ByVal sender As System.Object, ByVal e As _ System.EventArgs) Handles btnStart.Click Dim i As Integer, ValidErrors As Integer On Error GoTo ShowError ' Activate the error handler ValidErrors = 0 txtOutput.Text = "" For i = 0 To 1000 ' Those below 1000 are reserved Err.Raise(i) lblProgress.Text = "Processing error number: " & CStr(i) Me.Update() Next i lblProgress.Text = "Total useable error messages: " & CStr(ValidErrors) Exit Sub ShowError: If Err.Description <> UNUSED_ERROR_NUMBER Then txtOutput.Text &= Format(Err.Number, "000") & " " & Err.Description _ & vbCrLf ValidErrors += 1 End If Resume Next End Sub
The first thing to notice is the statement
On Error GoTo ShowError ' Activate the error handler
which enables the error handling. After the statement is executed and if an error is detected , Visual Basic .NET will direct program control to the first line of code following the label named ShowError. Toward the end of the btnStart Click event code, you'll see the ShowError label followed by the required colon.
The If statement checks to see whether Err.Description equals our previously defined symbolic constant for an unused error number. So, where did the Err object come from? Err is an object that Visual Basic .NET creates automatically for you when you run a program. As you can see from the code, Err.Description provides a short description of the error, whereas Err.Number holds the error number. The rest of the program behaves as before and the output is virtually identical to that shown in Figure 19.3.
After the On Error Goto statement, we enter a For loop that iterates through the list of predefined error numbers . The statement
causes Visual Basic .NET to set the error number to the value of i , thus generating the error condition. The error condition immediately causes Visual Basic .NET to send program control to the code associated with the ShowError label. We then execute the code that follows the ShowError label.
There are a few things about the program and unstructured error handling we need to point out.
If you look at the two code listings, you'll see that both of them contain the statement
In both cases, the statement is contained within the For loop that looks at the error messages. If you've studied the code, you'll have noticed that we want to display the value of the loop counter variable, i , on lblProgress as the program runs. This approach provides feedback to the user that the program is progressing.
As an experiment, try commenting out this line, and then recompiling and running the program. What happens? The program seems to go into never-never land for a few seconds and then it displays the final results shown in Figure 19.3. Without the form's Update() method call, the loop runs to completion before anything is displayed on the form. The purpose of Update() , therefore, is to update the screen to reflect the latest changes. In other words, Update() forces Windows to repaint the screen. Without the call, Windows repaints the screen only after the loop completed its execution.
Why is the call to Update() necessary? Why doesn't Windows just update the screen to display the new value written on the label the way the code tells it to? The reason is because it takes a considerable amount of time to repaint a screen. By default, if Visual Basic .NET is in a tight loop where some screen repainting is assumed, Visual Basic .NET postpones the screen updating until after the loop finishes. If you want to override this default behavior, you make the call to Update() at those points where you want the screen updated.
The last statement before the ShowError label is an Exit Sub statement. This statement is almost always necessary in unstructured error trapping routines. If you did not have an Exit Sub statement just before the error trap label (for example, ShowError ), Visual Basic .NET would fall into the error trapping code even if no error had occurred.
Always remember to place an Exit Sub at the point where you want to end the subroutine had no error occurred.
Toward the end of Listing 19.2, you'll see the statement
The Resume Next statement tells Visual Basic .NET to resume program execution at the next line following the line that generated the error condition. Because it was the Err.Raise() method that caused the error condition, program control is sent to the line that follows Err.Raise() , which is the statement
lblProgress.Text = "Processing error number: " & CStr(i)
This statement copies the current loop counter value onto the label. The call to Update() causes the screen to be repainted so that we can monitor the loop's progress.
As an alternative to Resume Next in Listing 19.2, you could use Resume . The Resume keyword causes Visual Basic .NET to send program control back to the same line that caused the error to occur in the first place. If we did this in our program, we would produce an infinite loop because we would continue to bounce back and forth between the Err.Raise() statement and the error processing code associated with ShowError .
In some cases, however, Resume provides the proper error handling. For example, if your program is trying to read a file on drive A, but the drive door is open , you could display a message telling the user to close the drive door and click the OK button. The Resume statement would then retry the line that sensed the open drive door and then try again to read the file.
On Error Goto 0
The On Error Goto 0 statement disables the error handler in the current procedure. This means that you can turn off an error handler at any point in a procedure with the On Error Goto 0 statement. However, any error handler in a procedure is disabled when program control leaves the procedure.
The statement On Error GoTo “1 also disables error trapping. Because error traps are disabled when program control leaves the procedure in which they are defined, you do not find too many programs that use either of these statements.
The On Error Goto statement and its associated statements provide an unstructured means for handling error conditions that might arise as the program executes. However, unstructured error processing is provided by Visual Basic .NET only to allow backward compatibility with earlier versions of Visual Basic. In its place, you're encouraged to use structured error processing.