Visual Studio VB.NET窗体项目System.OutOfMemoryException问题求助
解决VB.NET PictureBox切换图片时的System.OutOfMemoryException异常
问题描述
每次运行Visual Studio中的VB.NET窗体项目时,都会触发System.OutOfMemoryException异常。项目用于实现PictureBox切换不同广告图片的功能,尝试将图片格式从.png改为.jpg后问题依然存在。
原代码
Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick Dim gen As Random = New Random() Dim choice As Integer = gen.Next(0, 4) If choice = 0 Then PictureBox1.Image = Image.FromFile("Screenshot 2023-03-25 102759.jpg") ElseIf choice = 1 Then PictureBox1.Image = Image.FromFile("ad2.jpg") ElseIf choice = 2 Then PictureBox1.Image = Image.FromFile("ad4.jpg") Else PictureBox1.Image = Image.FromFile("ad5.jpg") End If End Sub
堆栈跟踪信息
StackTrace at System.Drawing.Image.FromFile(String filename, Boolean useEmbeddedColorManagement) at System.Drawing.Image.FromFile(String filename) at Word_game_prototype.Form1.Timer1_Tick(Object sender, EventArgs e) in C:\Visual studio (delete this junk)\Word game prototype\Word game prototype\Form1.vb:line 20 at System.Windows.Forms.Timer.OnTick(EventArgs e) at System.Windows.Forms.Timer.TimerNativeWindow.WndProc(Message& m) at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam) at System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg) at System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(IntPtr dwComponentID, Int32 reason, Int32 pvLoopData) at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context) at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context) at Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.OnRun() at Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.DoApplicationModel() at Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.Run(String[] commandLine) at Word_game_prototype.My.MyApplication.Main(String[] Args) in :line 83
问题根源
- 未释放旧图片资源:每次Timer触发时直接赋值新的Image对象,旧的Image资源未被释放,非托管内存持续占用,多次触发后引发内存不足。
- 重复从文件加载图片:每次都从磁盘读取图片,既浪费IO资源,也加剧内存占用。
- 重复创建Random实例:每次Tick都新建Random对象,可能导致随机数重复,但不是内存异常的直接原因。
解决方案
核心优化点
- 提前加载所有图片到内存,避免重复读取文件
- 切换图片时释放旧的Image资源
- 将Random声明为类级别变量,避免重复创建
修改后的完整代码
' 窗体级别变量,存储所有图片和随机数生成器 Private images As List(Of Image) = New List(Of Image)() Private rand As Random = New Random() Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load ' 窗体加载时一次性加载所有图片 images.Add(Image.FromFile("Screenshot 2023-03-25 102759.jpg")) images.Add(Image.FromFile("ad2.jpg")) images.Add(Image.FromFile("ad4.jpg")) images.Add(Image.FromFile("ad5.jpg")) End Sub Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick ' 释放当前PictureBox中的旧图片资源 PictureBox1.Image?.Dispose() ' 随机选择一张图片赋值 Dim choice As Integer = rand.Next(0, images.Count) PictureBox1.Image = images(choice) End Sub Private Sub Form1_FormClosing(sender As Object, e As FormClosingEventArgs) Handles MyBase.FormClosing ' 窗体关闭时释放所有加载的图片资源 For Each img In images img.Dispose() Next images.Clear() End Sub
额外注意事项
- 确保图片文件路径正确,若图片是项目嵌入资源,可改用
Assembly.GetExecutingAssembly().GetManifestResourceStream方式加载,避免文件路径依赖。 - 若图片尺寸过大,可考虑在加载时压缩图片分辨率,进一步减少内存占用。
内容的提问来源于stack exchange,提问作者Highlight Productions
相关产品推荐
相关产品推荐

