VB.NET启动窗体与Module Main()的选择及资源提取优化问题
VB.NET 资源提取避免循环及Module Main()启动配置
一、资源提取代码的放置位置(避免循环)
你的代码出现循环是因为AssemblyResolve事件触发时,在事件处理函数内加载资源会再次触发该事件(资源加载过程中可能需要解析依赖),导致重复执行提取逻辑。解决核心是一次性提取资源并缓存,事件处理时直接使用缓存数据,推荐以下两种放置位置:
1. 窗体的Load事件(启用应用框架时)
窗体Load事件仅在启动时执行一次,适合提前提取并缓存资源:
' 定义缓存字典,存储资源字节数组 Private cachedAssemblies As New Dictionary(Of String, Byte()) Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load ' 一次性提取所有资源到缓存 cachedAssemblies.Add("name0", My.Resources.resname0) cachedAssemblies.Add("name1", My.Resources.resname1) cachedAssemblies.Add("name2", My.Resources.resname2) End Sub Private WithEvents domain As AppDomain = AppDomain.CurrentDomain Private Function domainCheck(sender As Object, e As ResolveEventArgs) As Assembly Handles domain.AssemblyResolve ' 从缓存读取,避免重复提取和循环触发 For Each kvp In cachedAssemblies If e.Name.Contains(kvp.Key) Then Return System.Reflection.Assembly.Load(kvp.Value) End If Next Return Nothing End Function
2. 类的Shared构造函数(通用场景)
Shared构造函数在类第一次被访问时仅执行一次,无需依赖窗体事件:
' 静态缓存变量 Private Shared cachedAssemblies As Dictionary(Of String, Byte()) ' Shared构造函数,仅执行一次 Shared Sub New() cachedAssemblies = New Dictionary(Of String, Byte()) From { {"name0", My.Resources.resname0}, {"name1", My.Resources.resname1}, {"name2", My.Resources.resname2} } End Sub Private WithEvents domain As AppDomain = AppDomain.CurrentDomain Private Function domainCheck(sender As Object, e As ResolveEventArgs) As Assembly Handles domain.AssemblyResolve For Each kvp In cachedAssemblies If e.Name.Contains(kvp.Key) Then Return System.Reflection.Assembly.Load(kvp.Value) End If Next Return Nothing End Function
二、使用Module Main()作为启动项的配置方法
可以使用Module Main()作为启动入口,需要关闭“应用框架”并手动配置:
配置步骤
- 右键项目 → 选择属性
- 切换到应用选项卡
- 取消勾选启用应用框架
- 在启动对象下拉菜单中,选择包含
Sub Main()的模块(需提前创建该模块)
示例代码
Module MainModule Sub Main() ' 提前提取资源并缓存 Dim cachedAssemblies As New Dictionary(Of String, Byte()) From { {"name0", My.Resources.resname0}, {"name1", My.Resources.resname1}, {"name2", My.Resources.resname2} } ' 绑定AssemblyResolve事件,直接使用缓存 AddHandler AppDomain.CurrentDomain.AssemblyResolve, Function(sender, e) For Each kvp In cachedAssemblies If e.Name.Contains(kvp.Key) Then Return System.Reflection.Assembly.Load(kvp.Value) End If Next Return Nothing End Function ' 启动主窗体(如果需要) Application.Run(New Form1()) End Sub End Module
内容的提问来源于stack exchange,提问作者genesis lubrigas
相关产品推荐
相关产品推荐

