VB.NET Exception Handling – Processing All Members in a Loop

exception handlingloopsvb.net

Scenario:

I have a loop that iterates over an Array of COM objects and does some work using them.

My fear, working with COM objects, is that some exception will creep up (possibly on another user's environment) and cause the loop to break mid-way through processing these objects.

So, let's say (hypothetically) an exception occurs on file 32 of 173.

I see three options:

  1. Show the exception, inform the user that only 32 files were
    processed, and we then have to manually do the work on the remaining 141 files.

  2. Undo all the work done on the first 32 files, inform the user the
    request couldn't be completed and show the exception. This is less
    than ideal because by the time we are at this procedure, a lot of
    up-front work has been done (creating files, incrementing serial
    numbers, etc.) which would be cumbersome and difficult to undo. In the end, we end up with all 172 files needing manual work.

  3. Catch the exception, store it in a List, continue to try to
    process the rest of the files, then after trying to process all files, inform the user of any exceptions that occurred and any files which couldn't be processed. Best case we only have one file to manually do work on, and worst
    case we are left with 141 files – same as the first option.


Event horizon:

I'm new to programming. In fact I just wrote (am writing) my first add-in which I posted up on SE::Code Review.

Now, I'm of the mindset that option three makes the most sense – let's at least give hope a chance and see what happens with the rest of them, no?

So here's my implementation (well simplified, but this is the pattern):

Sub Main()
    Dim Exceptions as New List(of Exception)
    Try
        TryThatFunkyCOMthing (Exceptions)

        If Exceptions.Count>0 Then
            For Each ex As Exception in Exceptions
                MessageBox.Show(ex.ToString)
            Next
        End If

    Catch ex As Exception
        MessageBox.Show(ex.ToString)
    End Try
End Sub

Private Sub TryThatFunkyCOMthing (ByRef ExceptionBuffer as List(of Exception))
    For each COMthingy in COMthings
        Try
           COMthingy.DoSomething
        Catch ex As SpecificException
            COMthingy.WeAreBlewedUp
        Catch ex As Exception
            ExceptionBuffer.Add(ex)
        End Try
    Next
End Sub

One of the reviewers on CR gave me some feedback saying I should NOT be doing this. He said I should want the loop to stop if an exception occurs.

He linked to this SO Q&A regarding handling general exceptions, which I read (a few times now) and I think this solution falls under "failing gracefully". As mentioned above, I'm not trying to swallow exceptions, just control how/when they are handled so that my program behaves in a manner I can predict and depend on, even in the event of a catastrophic or unexpected exception.


What I'd like to know:

  1. If this is bad practice, why?
  2. Out of the three options I provided, which would you choose? – OR – Is there a mysterious and much better fourth option I'm missing?

Best Answer

I understand why you want to do this. The way you are doing it is not what I would do.

Rather than collect a list of exception objects, I would process those objects as they happen. By collecting a list to process later you run the risk of losing them before they get processed. At that point, without intending to do so, your program has swallowed the exceptions. The user will know nothing bad has happened. When they find out, the hard way, their experience with your program will be a poor one.

Whatever you want to do with the exceptions, do it as soon as they happen. Continue the loop if you like but process/log those exceptions regardless.

Related Topic