Microsoft.VisualBasic "My.Application" loads System.Web
While diagnosing causes of low memory on an application converted from VB6 to VB.NET, we ran across a situation in which the application loaded the System.Web
assembly (about 12MB) despite no user code referencing it.
The problem
After hooking the AppDomain.AssemblyLoad
event, it was eventually determined that System.Web
was being loaded by code calling My.Application.Info.DirectoryPath
. But why?
The stack trace when the AssemblyLoad event for System.Web was raised looked something like this:
- (event handler for assembly load event)
- …
System.Type.GetType(...)
Microsoft.VisualBasic.MyServices.Internal.SkuSafeHttpContext.InitContext()
- …
Microsoft.VisualBasic.MyServices.Internal.ContextValue<Utilities.My.MyApplication>.Value.get()
Utilities.MyUserCodeThatNeedsAssemblyPath
Apparently, calling My.Application
was creating a SkuSafeHttpContext
, whatever that was. Doing some quick Googling and even disassembling the module did not seem to reveal anything obvious.
Reproducing it
Creating a test application did not reproduce the problem: calling My.Application.*
from the constructor of a WPF window did not bring System.Web
along for the ride. Nor did calling it from the Application constructor of the project that I was trying to fix.
Eventually, it was determined that it was only when you call My.Application
from a separate assembly that this behaviour seems to manifest. In my test application, I set up something like this:
- Demo.sln
- Demo.vbproj [application project]
- DemoUtilities.vbproj [.NET Framework class library]
- Static method that calls
My.Application.Info.CurrentPath
- Static method that calls
This test successfully forced System.Web
to be loaded, with a callstack that looked very similar to our production application.
My hope is that this can help other developers in the future figure out why they may have phantom loads of the relatively large System.Web
assembly in their VB.NET applications.
Open Questions
I am still not sure why this happens. My assumption is that since My.Application
is intended to be a semi-global pseudo-namespace (it appears to have some magic for extending it), the developers of the VB.NET standard library determined that it should be a sort of singleton.
To avoid circular referencing, it is clear that they used some kind of decoupling mechanism so a “Helper” library does not need to know its owning application. I am not sure why they chose what appears from the signature to be an HTTP transport for this information. Could it be an analogue to .NET remoting?
ContextValue<T>
is basically only documented by Microsoft as being used to support the My
sugar, and also that we should never touch it.