Application.restart - Mysterious behavior in VB.Net

OK guys, what's going on here? In this VB code:

Module Module1 Sub Main() If MsgBox("Restart?", MsgBoxStyle.OkCancel) = MsgBoxResult.Ok Then Application.Restart() MsgBox("restarting") Else MsgBox("Cancel") End If End Sub End Module 

If this code is contained in a module, Application.Restart does not terminate the running application until End Sub is removed. Any code that appears before this is executed - for example, the message "Restart" appears. However, if the equivalent code runs on the form, then Application.Restart immediately terminates the application. (Both cases start the new instance correctly). This behavior does not appear to be documented anywhere - the documents imply that it is synonymous with "End" with respect to the completion of a working instance. Am I missing something?

+4
source share
2 answers

The best way to answer these questions is to look at the code itself using Reflector (or Microsoft is free to debug code when it is available).

With Reflector, you can see (in the .NET Framework 4.0) System.Windows.Forms.Application.Restart looking for four different types of applications:

  • initial check that Assembly.GetEntryAssembly is Nothing , throwing a NotSupportedException , if so:
  • Process.GetCurrentProcess.MainModule.FileName is located ieexec.exe in the same folder as the current .NET Framework (in particular, the folder in which the module that defines Object );
  • ApplicationDeployment.IsNetworkDeployed - True ; and
  • general case.

All three supported cases determine how to restart the process, call Application.ExitInternal and start the process again.

Application.ExitInternal closes open forms, including validating a form that attempts to abort the closure by setting FormClosingEventArgs.Cancel to True . If the form is not canceled, the forms are closed and, using ThreadContext.ExitApplication , all ThreadConnexts are cleared ( Disposed or their ApplicationContext.ExitThread is called).

NB No Thread.Abort , so threads are NOT explicitly closed in any way. Also, Windows.Forms ModalApplicationContext does not even raise the ThreadExit event, which makes a regular ApplicationContext .

(Note that all three supported cases in Application.Restart ignore the result of Application.ExitInternal , so if a form tries to abort everything that happens, any other forms do not get the opportunity to close, and ThreadContexts are not cleared!)

It is important to note that it is NOT trying to actually exit the current threads or the entire application (except for closing open forms and thread contexts).

However, by the time you launch your MsgBox("restarting") new application.

You need to manually exit the application after calling Application.Restart . In the case of "run [ing] on the form" (you do not show the code in which you tested it), either the form is closed, and this is what you considered the current application termination, or additional material that Windows.Forms (or VB) means that the application exits one of the “events” that are thrown when the cleanup that actually occurs is performed.

In other words, before testing, I expected MsgBox appear even if this code is in the Click state of the form, the form first disappears and the application restarts at the same time.

After testing it, MsgBox will appear, since I hear a sound signal corresponding to it, and if I comment on it, there will be no sound signal. Therefore, something forces the application to exit, although it should have a message box, and even placing the MsgBox in Finally outside Application.Run does not appear on Restart . (Note that a similar effect is observed if you call MsgBox after Application.Exit .)

So, something configured using Windows.Forms (or VB) does indeed call something like Environment.Exit , which calls Win32Api ExitProcess and does not consider Finally or calls Dispose or Finalize .

Please note that the Application.Restart documentation implies that it is not for console applications, although it currently works fine (except that you do not immediately leave, which is not implied by Application.Exit ).

+3
source

This will admittedly be a bit of an assumption based on some pretty high level of reading I did about Application.Restart (), but I think this is because Restart works internally.

I think that Restart () is trying to do as much “smart” cleaning as possible for the process that is ending, and in what might be considered a rather simplified implementation, it keeps track of some things that need to be “cleaned”, “maybe calling Dispose () on them (if applicable), which is usually a reasonable step. In your case, I’m going to assume that the background thread or form contains a link to something - I can’t say that - this prevents the code from closing. It can realize that it runs inside a method and wants to give this method a possible to complete it before killing him - waiting for the completion of this sub / method.

I saw that other instances of Restart did indeed cause a really strange "Collection is Modified" error when no collection was involved. What is supposedly naive to me is probably naive that the internal cleanup that Restart is trying to do is carried over to a simple list, but under certain circumstances the cleanup modifies an item in an unexpected way, the way that modifies the collection throws an exception to be thrown and abort exit / restart .

0
source

Source: https://habr.com/ru/post/1435556/


All Articles