# Any VB.Net programmers?  Infinite recursion error when closing

**URL:** <https://boards.straightdope.com/t/any-vb-net-programmers-infinite-recursion-error-when-closing/479566>\
**Category:** Factual Questions\
**Created:** [January 2, 2009, 6:24am UTC](https://boards.straightdope.com/t/any-vb-net-programmers-infinite-recursion-error-when-closing/479566 "2009-01-02T06:24:57Z")\
**Posts on this page:** 11\
**Page:** 1

<div class="post-metadata">

**Author:** ![tim314](https://sea3.discourse-cdn.com/straightdope/user_avatar/boards.straightdope.com/tim314/32/3468_2.png) [@tim314](https://boards.straightdope.com/u/tim314)\
**Post date:** [January 2, 2009, 6:24am UTC](https://boards.straightdope.com/t/any-vb-net-programmers-infinite-recursion-error-when-closing/479566/1 "2009-01-02T06:24:57Z")

</div>

My program ends when Form1 closes. However, the program closes without calling the FormClosed events of Form2 and Form3. This is bad, because I need to make sure the data in Form2 and Form3 is saved.

So I add code to make sure those forms are properly closed:

```auto

Private Sub Form1_FormClosed(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosedEventArgs) Handles Me.FormClosed
        SaveForm1Data()
        Form2.Close()
        Form3.Close()
End Sub

Private Sub Form2_FormClosed(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosedEventArgs) Handles Me.FormClosed
        SaveForm2Data()
End Sub

Private Sub Form3_FormClosed(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosedEventArgs) Handles Me.FormClosed
        SaveForm3Data()
End Sub

```

This works fine. But then I decided I want the program to close if _any_ of the three forms is closed. My first thought was to make it so that closing the other forms causes Form1 to close:

```auto

Private Sub Form2_FormClosed(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosedEventArgs) Handles Me.FormClosed
        SaveForm2Data()
        Form1.Close()
End Sub

Private Sub Form3_FormClosed(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosedEventArgs) Handles Me.FormClosed
        SaveForm3Data()
        Form1.Close()
End Sub

```

But then I get stuck in an infinite loop between the different form’s FormClosed events. Form1 closes Form2 closes Form1 closes Form2 . . . .

I suppose I could fix this by adding a variable to each form to tell if we’ve already called its FormClosed event once before. But is there a more elegant way? Should I perhaps be using Application.Exit() or End instead of Form1.Close?

---

<div class="post-metadata">

**Author:** ![Sage\_Rat](https://sea3.discourse-cdn.com/straightdope/user_avatar/boards.straightdope.com/sage_rat/32/399_2.png) [@Sage\_Rat](https://boards.straightdope.com/u/Sage_Rat)\
**Post date:** [January 2, 2009, 6:30am UTC](https://boards.straightdope.com/t/any-vb-net-programmers-infinite-recursion-error-when-closing/479566/2 "2009-01-02T06:30:40Z")

</div>

Why does the program end without calling close on the other two forms? I.e. why is it aware of form1 but not 2 and 3?

---

<div class="post-metadata">

**Author:** ![tim314](https://sea3.discourse-cdn.com/straightdope/user_avatar/boards.straightdope.com/tim314/32/3468_2.png) [@tim314](https://boards.straightdope.com/u/tim314)\
**Post date:** [January 2, 2009, 7:02am UTC](https://boards.straightdope.com/t/any-vb-net-programmers-infinite-recursion-error-when-closing/479566/3 "2009-01-02T07:02:13Z")

</div>

> [@Sage\_Rat](#):
>
> Why does the program end without calling close on the other two forms? I.e. why is it aware of form1 but not 2 and 3?

Form1 is my startup Form (the first one opened).

In the Project Properties menu you can choose either to shut down when the startup form closes or when the last open form is closed. I have it set up to shut down when the startup form closes.

But what I really want is to make it shut down when _any_ form closes, but only after calling the FormClosed events of all the other forms.

---

<div class="post-metadata">

**Author:** ![Stealth\_Potato](https://avatars.discourse-cdn.com/v4/letter/s/d78d45/32.png) [@Stealth\_Potato](https://boards.straightdope.com/u/Stealth_Potato)\
**Post date:** [January 2, 2009, 7:58am UTC](https://boards.straightdope.com/t/any-vb-net-programmers-infinite-recursion-error-when-closing/479566/4 "2009-01-02T07:58:53Z")

</div>

A better solution would be to simply call Application.Exit() in each form’s FormClosed handler (after saving your important data). Application.Exit() will signal all forms in the application to close as soon as they stop processing messages, and all of your remaining FormClosed handlers will be called.

(The FormClosed handler that calls Application.Exit() will not be called again, because Application.Exit only raises FormClosing (and subsequent FormClosed) events for all currently _open_ forms, and since the form that just received a FormClosed event is no longer open, it won’t receive any further events.)

So, something like this:

```auto

Private Sub Form1_FormClosed(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosedEventArgs) Handles Me.FormClosed
        SaveForm1Data()
        Application.Exit()
End Sub

```

…And similarly for the other forms. Note: I’m only relatively certain that it will be written exactly as “Application.Exit()”; I have never programmed in Visual Basic, but I have been using .NET in C# for years, and most of this stuff is extremely consistent across the various .NET languages.

---

<div class="post-metadata">

**Author:** ![tim314](https://sea3.discourse-cdn.com/straightdope/user_avatar/boards.straightdope.com/tim314/32/3468_2.png) [@tim314](https://boards.straightdope.com/u/tim314)\
**Post date:** [January 2, 2009, 8:27am UTC](https://boards.straightdope.com/t/any-vb-net-programmers-infinite-recursion-error-when-closing/479566/5 "2009-01-02T08:27:42Z")

</div>

Thanks, **Stealth Potato**. That does seem to work better.

Interestingly, Microsoft’s documentation [claims](http://msdn.microsoft.com/en-us/library/system.windows.forms.application.exit(VS.71).aspx) that Application.Exit() _won’t_ raise the forms’ Closed events.

> [@](#):
>
> CAUTION The Form.Closed and Form.Closing events are not raised when the Application.Exit method is called to exit your application. If you have validation code in either of these events that must be executed, you should call the Form.Close method for each open form individually before calling the Exit method.

In fact, seeing that was what made me assume I should be using Form1.Close() instead of Application.Exit() in the first place.

But having just now tried it out, it seems that you’re right and the MSDN documentation is wrong.

---

<div class="post-metadata">

**Author:** ![Stealth\_Potato](https://avatars.discourse-cdn.com/v4/letter/s/d78d45/32.png) [@Stealth\_Potato](https://boards.straightdope.com/u/Stealth_Potato)\
**Post date:** [January 2, 2009, 9:29am UTC](https://boards.straightdope.com/t/any-vb-net-programmers-infinite-recursion-error-when-closing/479566/6 "2009-01-02T09:29:17Z")

</div>

Well, it all depends on what version of the .NET framework you’re targeting. The MSDN documentation page you’ve linked to is for one of the earlier versions, 1.1, and it’s correct as far as it goes. But you’re probably targeting 2.0 at least, if not 3.0 or 3.5. (It’s an option in your project settings.)

Note that your methods are handling the event System.Windows.Forms.Form. **FormClosed** , and _not_ System.Windows.Forms.Form. **Closed**. It’s a very subtle difference, and probably the source of your initial confusion: the Closed event (and corresponding Closing event) was originally from .NET 1.1, and was made obsolete in .NET 2.0 with the introduction of the FormClosed and FormClosing events. They have the same purpose; Microsoft basically decided that FormClosed and FormClosing were better names, but kept the originals around as well for backwards-compatibility.

Application.Exit() in .NET 1.1 **did not** raise Closing or Closed events; it was necessary to do this manually. When .NET 2.0 came around, Application.Exit() was updated so that it **did** raise FormClosing and FormClosed events for all currently open forms. However, it still does not raise Closing or Closed events, since those are deprecated as of .NET 2.0.

So, long story short, Application.Exit() _does_ raise Form.FormClosed, it _doesn’t_ raise Form.Closed, and any confusion between the two is simply the result of Microsoft’s perennial hobgoblin of backwards compatibility. 😛

---

<div class="post-metadata">

**Author:** ![tim314](https://sea3.discourse-cdn.com/straightdope/user_avatar/boards.straightdope.com/tim314/32/3468_2.png) [@tim314](https://boards.straightdope.com/u/tim314)\
**Post date:** [January 2, 2009, 10:01am UTC](https://boards.straightdope.com/t/any-vb-net-programmers-infinite-recursion-error-when-closing/479566/7 "2009-01-02T10:01:33Z")

</div>

Ah, that explains it. Thanks again, **Stealth Potato**!

---

<div class="post-metadata">

**Author:** ![Mbossa](https://avatars.discourse-cdn.com/v4/letter/m/73ab20/32.png) [@Mbossa](https://boards.straightdope.com/u/Mbossa)\
**Post date:** [January 2, 2009, 12:20pm UTC](https://boards.straightdope.com/t/any-vb-net-programmers-infinite-recursion-error-when-closing/479566/8 "2009-01-02T12:20:38Z")

</div>

> [@Stealth\_Potato](#):
>
> They have the same purpose; Microsoft basically decided that FormClosed and FormClosing were better names, but kept the originals around as well for backwards-compatibility.

I reckon it’s more likely that Microsft realised that Application.Exit() _should_ raise the Closing and Closed events, but by the time they realised this, there were already applications out there that depended on these events _not_ being raised. Rather than change .NET to automatically raise these events, which could potentially break legacy apps, they decided to deprecate those events and introduce new ones with different names that are raised when they should be.

Not that this matters for the OP. I just enjoy speculating about the rationale behind certains decisions made by the .NET team.

---

<div class="post-metadata">

**Author:** ![Stealth\_Potato](https://avatars.discourse-cdn.com/v4/letter/s/d78d45/32.png) [@Stealth\_Potato](https://boards.straightdope.com/u/Stealth_Potato)\
**Post date:** [January 2, 2009, 6:42pm UTC](https://boards.straightdope.com/t/any-vb-net-programmers-infinite-recursion-error-when-closing/479566/9 "2009-01-02T18:42:19Z")

</div>

Hmm. I suppose that is a more plausible explanation. “Form.FormClosed” does seem a bit redundant and out of line with the usual event naming conventions. An unfortunate choice, however you slice it; but then, fear of breaking legacy apps is a huge motivator of Microsoft’s API design choices. :o

---

<div class="post-metadata">

**Author:** ![tim314](https://sea3.discourse-cdn.com/straightdope/user_avatar/boards.straightdope.com/tim314/32/3468_2.png) [@tim314](https://boards.straightdope.com/u/tim314)\
**Post date:** [January 2, 2009, 7:57pm UTC](https://boards.straightdope.com/t/any-vb-net-programmers-infinite-recursion-error-when-closing/479566/10 "2009-01-02T19:57:50Z")

</div>

> [@Mbossa](#):
>
> I reckon it’s more likely that Microsft realised that Application.Exit() _should_ raise the Closing and Closed events, but by the time they realised this, there were already applications out there that depended on these events _not_ being raised. Rather than change .NET to automatically raise these events, which could potentially break legacy apps, they decided to deprecate those events and introduce new ones with different names that are raised when they should be.

Maybe so, but if that’s the case wouldn’t it have been easier and more sensible to just add a new method that fills the role of Application.Exit() while also raising Closing and Closed events?

They could have called it something like Application.CloseAll()

---

<div class="post-metadata">

**Author:** ![Khadaji](https://avatars.discourse-cdn.com/v4/letter/k/9e8a1a/32.png) [@Khadaji](https://boards.straightdope.com/u/Khadaji)\
**Post date:** [January 2, 2009, 9:15pm UTC](https://boards.straightdope.com/t/any-vb-net-programmers-infinite-recursion-error-when-closing/479566/11 "2009-01-02T21:15:31Z")

</div>

> [@tim314](#):
>
> Maybe so, but if that’s the case wouldn’t it have been easier and more sensible to just add a new method that fills the role of Application.Exit() while also raising Closing and Closed events?
> 
> They could have called it something like Application.CloseAll()

Well, you could go through the Application.OpenForms collection and call each one’s close method.
