1

I get hit with this System.OutOfMemoryException every time I try the project.

This was supposed to change the picture box to different pictures (ads). I tried changing the picture formats, they were .png files and now .jpg files.

Here is the code:

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

and here is the stack trace:

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
Joel Coehoorn
  • 399,467
  • 113
  • 570
  • 794

3 Answers3

1

Do this, to avoid re-loading the file from disk on every tick:

' Define these at the class level, not in the method
Private Images As New List(Of Image) From {
      Image.FromFile("Screenshot 2023-03-25 102759.jpg"),
      Image.FromFile("ad2.jpg"),
      Image.FromFile("ad4.jpg"),
      Image.FromFile("ad5.jpg")
}

' Random objects should be Long-lived
Private gen As New Random()

' And suddenly this can be a one-liner, too
Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
    PictureBox1.Image = Images(gen.Next(0, 4))
End Sub
Joel Coehoorn
  • 399,467
  • 113
  • 570
  • 794
1

According to the Image.FromFile documentation, a OutOfMemoryException is thrown if:

The file does not have a valid image format.

or

GDI+ does not support the pixel format of the file.

And there are multiple other reasons. One of the most likely is that the file is open multiple times, in which case it's better to use Image.FromStream() instead of Image.FromFile, see https://stackoverflow.com/a/2216338/217666.

So as an alternative to the answer suggesting caching the image objects, you can define and use a safe function for loading image files:

Private Shared Function OpenImage(imageFile As String) As Image
    Using fs As FileStream = New FileStream(imageFile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)
        Return Image.FromStream(fs)
    End Using
End Function


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 = OpenImage("Screenshot 2023-03-25 102759.jpg")
    ElseIf choice = 1 Then
        PictureBox1.Image = OpenImage("ad2.jpg")
    ElseIf choice = 2 Then
        PictureBox1.Image = OpenImage("ad4.jpg")
    Else
        PictureBox1.Image = OpenImage("ad5.jpg")
    End If
End Sub
Peter Macej
  • 4,831
  • 22
  • 49
0

Fixed the issues looked like the images didn't survive the conversion so i had to get a fresh copy of the images and now they work. thanks for all of the helpful tips tho.