JPG file being kept as accessed by program

L

Lloyd Sheen

I have a problem in a program in which a jpg file which is being used to
load the Image of a picturebox is being kept after the load.

The code is as follows:

Public ReadOnly Property ImageUrl() As Image
Get
If theImage Is Nothing Then
Dim jpgs() As String = Directory.GetFiles(Me.FolderName, "*.jpg")
If jpgs.Length > 0 Then
Try
Dim theTempImage As Image = Image.FromFile(jpgs(0))
theImage = CType(theTempImage.Clone, Image)
theTempImage.Dispose()
'theImage = Image.FromFile(jpgs(0))
Catch ex As Exception
Dim x As Integer = 1
Return Nothing
End Try
Return theImage
Else
Return Nothing
End If
Else
Return theImage
End If
End Get
End Property

As you can see I tried to get rid of the problem by cloning the first
image and then disposing it to get rid of the "reference" to the jpg
file. That does not work.

The problem occurs in the app if I attempt to delete the folder while it
is being shown in a list (the ImageURL property is used for databinding).

Any ideas on how to load the image without keeping a reference to the file?

Thanks
LS
 
B

Bill McCarthy

Hi Lloyd,

What you can do is take control of the stream, e.g:

Dim path as String ="some picture.jpg"
Dim st As New IO.FileStream(path, IO.FileMode.Open,
IO.FileAccess.Read)
Dim img As Image = Drawing.Image.FromStream(st, False, False)

While st.Position <> st.Position
Application.DoEvents()
' might need a sleep in here
End While
st.Close()


Note you can't close the stream until after the stream has been read. If
the above doesn't work in your scenario, and it is a bit questionable, then
you can use a ReadOnceStream, e.g:

Class ReadOnceStream
Inherits IO.FileStream

Sub New(ByVal path As String, ByVal mode As IO.FileMode, ByVal access As
IO.FileAccess)
MyBase.New(path, mode, access)
End Sub

Public Overrides Function Read(ByVal array() As Byte, ByVal offset As
Integer, ByVal count As Integer) As Integer
Dim result = MyBase.Read(array, offset, count)
If Position >= Length Then Me.Close()
Return result
End Function
End Class

And use it like :

Dim path as String ="some picture.jpg"
Dim st As New ReadOnceStream(path, IO.FileMode.Open,
IO.FileAccess.Read)
Dim img As Image = Drawing.Image.FromStream(st, False, False)


Once the stream is read from it closes itself, so you don't need to dispose
etc.
 
B

Bill McCarthy

Bill McCarthy said:
Hi Lloyd,

What you can do is take control of the stream, e.g:

Dim path as String ="some picture.jpg"
Dim st As New IO.FileStream(path, IO.FileMode.Open,
IO.FileAccess.Read)
Dim img As Image = Drawing.Image.FromStream(st, False, False)

While st.Position <> st.Position

Actually I meant While st.Position < st.Length, but that doesn't work. (it
can in some cases, but it can also cycle infinitely) Just a single DoEvents
works here in a UI application as it gives the image a chance to render,
*if* you have assinged the image to be rendered.

e.g :
Dim st As New IO.FileStream(path, IO.FileMode.Open, IO.FileAccess.Read)
Dim img As Image = Drawing.Image.FromStream(st, False, False)
Me.PictureBox1.Image = img

While st.Position < st.Length
Application.DoEvents()
End While

st.Close()

This works, but if you remove the
PictureBox1.Image = img
then it will loop infinitely

I think the ReadOnceStream (below) is much more robust, but again you have
to be careful of scope. The most important thing is in both cases you
really need to force the rendering or remove the image and manually close
the stream.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top