Wed, September 1, 2004, 10:20 AM under
Whidbey |
VisualStudio
With VS2005, VB gets the
My feature. Part of the package is a new startup model and
MyEvents.
If you look in a VB project properties, you will find a (unchecked by default) checkbox "Startup with custom Sub Main". Below it there are more "Windows Application Properties", including choosing a Splash screen. There is also a button "View Code" which takes you to the partial MyApplication class - you can also go there by showing all files in the solution explorer and navigating to the MyEvents.vb file under My Project. By using the dropdown you can hook into various events e.g. Startup, UnhandledException etc. So how does this work?
Well the first thing to note is that,
if you check the "Startup with custom Sub Main" (and provide your own Sub Main OR use the implicit one of a Form1), then none of the events will be caught, so obviously the two are intertwined. Second, if you use the
Class Designer to drag the MyApplication class on a diagram and then display the full hierarchy, you will find that it inherits from WindowsFormsApplicationBase (WFAB), which in turn inherits from ApplicationBase. All of these are in the System.Windows.Forms namespace
but are defined in the Microsoft.VisualBasic.dll
To continue the exploration, we build a simple VB WindowsApplication in Release mode and place a Trace.Assert(False, “stack") in its Form.Load event handler. After running the app, we see the stack trace in a msgbox that uncovers the startup call path. Usually we'd expect to see our Sub Main function followed by Application.Run and then a whole bunch of other methods (not of interest right now) ending up in Form1_Load. Instead, we notice that the call stack starts with:
MyApplication.Main -> WFAB.Run -> WFAB.DoApplicationModel -> WFAB.OnRun -> Application.Main etc.
And those methods are where the magic is.
OnRun does the following:
-sets the MainForm to be your main form (via OnCreateMainForm)
-hides the splash screen
-sets up the NetworkAvailabilityChanged event
-calls Application.Run
DoApplicationModel does the following:
-shows the splash screen (via OnInitialize)
-Raises the Startup event (via OnStartup)
-calls OnRun (just described above)
-raises the Shutdown event (via OnShutdown)
So
how does all this affect the startup performance of VB apps compared to C#? I don't have that answer, but if you go and look in the methods above, you will find a whole bunch of other objects getting created (relative to thread safety, security etc). Also take into account the call path for the creation of MyApplication, e.g. it is in the WFAB.ctor that the StartupNextInstance event gets hooked.
Finally, a separate note on the UnhandledException event: This is setup in DoApplicationModel by hooking into the Application.ThreadException event. DoApplicationModel can also raise the UnhandledException event as a result of an exception occurring around (effectively) Application.Run.
We know that there are 3 actions one must take to catch all unhandled exceptions, instead here we see only two! So it is obvious that
the AppDomain.UnhandledException has to be separatelly subscribed to by the developer (for catching thread exceptions other than the GUI). I think this is a gotcha and the VB team should also hook into it so that when we catch the UnhandledException in MyEvents.vb we really are catching all unhandled exceptions.
Next time we'll look at the possibility of using this approach (including catching the events) from C#.