Help: buggy activity in compact .net app

  • Thread starter Thread starter Sarah Smith
  • Start date Start date
S

Sarah Smith

Hi Guys,

I am learning to code .Net apps for my PDA. To start with, i'm making
a slide show app.

I have a string array which holds the names of image files found in a
folder on the device on an SD Card. The app then loops through this
array moving through the elements once avery couple of seconds
(timer).

I then us this code to create a bitmap from the path

strFullpath = "\SD Card\" & strFilesarray(x)

'where X is the loop counter.

Before I call the function to grab a bitmap from the file/path, I
check that the string is not empty. So far, so good:


If strFullPath = "" Then
MsgBox("Error: path string empty!")
Return
End If

'I then do this:

Dim myBitMap As Bitmap

myBitMap = MakeBitMap(strFullPath)

'Here are the guts of my MakeBitmap function:

Private Function MakeBitMap(ByVal strPath As String) As Bitmap

Try
Dim MyBitmap As New Bitmap(strPath) '*error occurs here
Return MyBitmap

Catch ex As Exception
MsgBox("Error: " & ex.Message & " in MakeBitMap()")
Return Nothing
End Try

End Function

As you can see, it is pretty straight forward. But ... after looping
successfully for the first time, the app generates an error
(BadArgumentException) about half way through the second loop.

I know the filepath is good because of the check it makes before
calling the MakeBitmap() function.

Does anyone have an idea as to what could be causing the error?
 
Before invoking MakeBitmap to load anothe bitmap, try calling .Dispose on
the one you had already.

Something like this:
If Not myBitmap is Nothing Then
myBitmap.Dispose()
End if

myBitmap = MakeBitmap(...)
 
And also make sure that the file actually exists:

If File.Exists(strPath) Then
/'bla, bla bla
End if
 
Hi Alex,

thanks for your suggestions.

I think the code is OK, and the error is a bug in the CF.

I don't need to check the path (as you indicate below), because the
path has been verified earlier.

As for using .Dispose() on the bitmap object ... I don't think that is
usefull either because the bitmap is created inside a routine.

Like this:

Dim strFullPath As String
strFullPath = strRoot & "\" & strFilenames(nCount)

If strFullPath = "" Then
MsgBox("Error: path string empty!")
Return
End If

Dim myBitMap As Bitmap
myBitMap = MakeBitMap(strFullPath)

If myBitMap Is Nothing Then
MsgBox("Error with: " & strFilenames(nCount))
Return
End If

I moved the code in the MakeBitmap() function just to handle debugging
a little better. So as you can see, each time the code is ready to
call the MakeBitMap() function, it creates a New Bitmap anyway.

Or is the CF runtime doing something that is not normal?

I always thought that when you enter a routine, local variables are
created, and then when the routine loses scope, and you are returned
to the calling routine, the local variables are destroyed.

Doesn't the CF runtime work this way?

-SS
 
The variable is destroyed, but there is nothing to guarantee immediate
disposal of the resources it needed. Calling Dispose (and maybe even
GC.Collect) would help the EE know what to do. Myself I'd probably use a
class-scoped variable for the bitmap that I create only once per app
instance. This would avoid the entire situation.

-Chris
 
Actually the whole point of doing what I suggested was to make sure bitmap
data is freed from memory *before* the next one is loaded. She might only
have enough memory for one bitmap
 
Sara,

Why don't you at least try the suggested steps? As it happens, nearly 100%
of developers think their code is ok and there is something wrong with
OS/Library/Framework. After dust settles, only 99% of them have proven
themselves right.

That said, there *are* bugs in CF, but to confirm it someone will need to
see repro code
 
Out of curiosity (and because I know you've looked at this stuff and I
haven't), if she went with a single global and re-loaded it as needed, what
are the memory implications? Does an entirely new block get allocated when
the Bitmap is reloaded with another image, or is the original memory chunk
re-used if possible?

-Chris
 
Thank you both. I will try the steps you mentioned.

I'll post back the results if you're interested.

Thanks a lot.

S.S
 
Hi,

It still doesn't work correctly.


This is all of the code from the 2 routines. The first one:
Showimage() is called either from a navigation button, or from a Timer
event (for a slide show).

The variables: strRoot and strFilenames() are populated in button or
form events:

The error message is always "Bad Argument Exception" when trying to
create a new bitmap in the MakeBitmap() function.

The app can loop through about 40 images, but on the second run, it
raises the exception about have way through.

FYI: the images are stored on an SD Card, are JPG format, and the
device and os is a Dell Axim X5 with WM 2003.

the error does _not_ occur in the emulator.

S.S


Private Sub ShowImage()

On Error GoTo Trap
'Picture box width: 224, hieght: 232
Me.picBox1.Width = 224
Me.picBox1.Height = 232
Me.picBox1.SizeMode = PictureBoxSizeMode.StretchImage


Me.Text = strFilenames(nCount).ToString

Dim strFullPath As String
strFullPath = strRoot & "\" & strFilenames(nCount)

If strFullPath = "" Then
MsgBox("Error: path string empty!")
Return
End If

Dim myBitMap As Bitmap

If Not myBitMap Is Nothing Then
myBitMap.Dispose()
End If

myBitMap = MakeBitMap(strFullPath)

If myBitMap Is Nothing Then
MsgBox("Error with: " & strFilenames(nCount))
Return
End If

If myBitMap.Width < Me.picBox1.Width Then

Else
'The aspect ratio of an image is the width / hieght
'get the aspect ratio of the image:
Dim aspInt As Double
aspInt = myBitMap.Width / myBitMap.Height
Me.picBox1.Height = CInt(Me.picBox1.Width / aspInt)
Me.picBox1.SizeMode = PictureBoxSizeMode.StretchImage

End If

'Set the new bitmap to be the Image of the picture box:
Me.picBox1.Image = myBitMap

Exit Sub

Trap:
MsgBox("Error: " & Err.Description & " ..in ShowImage()")
'Resume Next
Timer1.Enabled = False

End Sub


Private Function MakeBitMap(ByVal strPath As String) As Bitmap

Try
Dim MyBitmap As Bitmap
If Not MyBitmap Is Nothing Then
MyBitmap.Dispose()
End If

MyBitmap = New Bitmap(strPath) '<---error here
Return MyBitmap

Catch ex As Exception
MsgBox("Error: " & ex.Message & " in MakeBitMap()")
Return Nothing
End Try

End Function
 
I don't see that it possibly could reuse the memory. If the 1st bitmap was
disposed, then the memory is available and if it was not, then the memory is
still in use and is untouchable.
 
I guess my question is this. How would this impact memory, assuming
"bitmaps" is an array of string paths?

Bitmap b;

for(i = 0 ; i < bitmaps.count ; i++)
{
b = new Bitmap(bitmaps.ToString());
}


--
Chris Tacke, eMVP
Co-Founder and Advisory Board Member
www.OpenNETCF.org
---
Windows CE Product Manager
Applied Data Systems
www.applieddata.net


Alex Feinman said:
I don't see that it possibly could reuse the memory. If the 1st bitmap was
disposed, then the memory is available and if it was not, then the memory is
still in use and is untouchable.

Chris Tacke said:
Out of curiosity (and because I know you've looked at this stuff and I
haven't), if she went with a single global and re-loaded it as needed, what
are the memory implications? Does an entirely new block get allocated when
the Bitmap is reloaded with another image, or is the original memory chunk
re-used if possible?

-Chris

Alex Feinman said:
Actually the whole point of doing what I suggested was to make sure bitmap
data is freed from memory *before* the next one is loaded. She might only
have enough memory for one bitmap

"Chris Tacke, eMVP" <ctacke[at]Open_NET_CF[dot]org> wrote in message
The variable is destroyed, but there is nothing to guarantee immediate
disposal of the resources it needed. Calling Dispose (and maybe even
GC.Collect) would help the EE know what to do. Myself I'd probably
use
a
class-scoped variable for the bitmap that I create only once per app
instance. This would avoid the entire situation.

-Chris



Hi Alex,

thanks for your suggestions.

I think the code is OK, and the error is a bug in the CF.

I don't need to check the path (as you indicate below), because the
path has been verified earlier.

As for using .Dispose() on the bitmap object ... I don't think
that
 
The card is manufactured in taiwan by Apacer. (32mb).

.... I've just tried moving the images to the My Documents\My
Pictures folder ... with the same result.

"Error: ArgumentException in MakeBitMap()"

... so it's not the card :-(
S.S
 
Hello Sarah,

Please could you answer a few questions so we could to narrow the problem
down?

When you first time load images, can you open all images from the list?
Does the problem occur only when you are trying to load the images second
time.

If an exception is thrown during the first loop, then please make sure that
the image that failed to load can be opened on the device at all (i.e. can
be opened from File Explorer by taping on the image). I'm asking to do this
in order to make sure that format of the image is supported by the OS. If
it is not, then the .NET Compact Framework will not be able to load it.

Also looking at your ShowImage() method, I noticed that the bitmap that is
assigned to the picturebox is never disposed. This will result in a
situation, when the device does not have enough memory to load another
image. Please try to change you code as the following:

'Set the new bitmap to be the Image of the picture box:
If Not (Me.picBox1.Image Is Nothing) Then // add this code
Me.picBox1.Image.Dispose() // add this code
End If // add this code
Me.picBox1.Image = myBitMap


I hope this helps.

Best regards,
Sergiy.


This posting is provided "AS IS" with no warranties, and confers no rights.
--------------------
| From: Sarah Smith <[email protected]>
| Subject: Re: buggy activity in compact .net app
| Date: Mon, 02 Feb 2004 20:12:53 +0100
| Message-ID: <[email protected]>
| References: <[email protected]>
<[email protected]>
<#[email protected]>
<[email protected]>
<[email protected]>
<[email protected]>
<[email protected]>
<[email protected]>
| X-Newsreader: Forte Agent 1.91/32.564
| MIME-Version: 1.0
| Content-Type: text/plain; charset=us-ascii
| Content-Transfer-Encoding: 7bit
| Newsgroups: microsoft.public.dotnet.framework.compactframework
| NNTP-Posting-Host: 0x50c48e18.adsl-fixed.tele.dk 80.196.142.24
| Lines: 1
| Path:
cpmsftngxa07.phx.gbl!cpmsftngxa06.phx.gbl!TK2MSFTNGP08.phx.gbl!TK2MSFTNGP11.
phx.gbl
| Xref: cpmsftngxa07.phx.gbl
microsoft.public.dotnet.framework.compactframework:44644
| X-Tomcat-NG: microsoft.public.dotnet.framework.compactframework
|
|
| The card is manufactured in taiwan by Apacer. (32mb).
|
| .... I've just tried moving the images to the My Documents\My
| Pictures folder ... with the same result.
|
| "Error: ArgumentException in MakeBitMap()"
|
| ... so it's not the card :-(
| S.S
|
|
| On Mon, 2 Feb 2004 09:41:03 -0800, "Alex Feinman [MVP]"
|
| >Is it a SanDisk SD card? Can you try doing this on another device?
| >
| >| >>
| >> Hi,
| >>
| >> It still doesn't work correctly.
| >>
| >>
| >> This is all of the code from the 2 routines. The first one:
| >> Showimage() is called either from a navigation button, or from a Timer
| >> event (for a slide show).
| >>
| >> The variables: strRoot and strFilenames() are populated in button or
| >> form events:
| >>
| >> The error message is always "Bad Argument Exception" when trying to
| >> create a new bitmap in the MakeBitmap() function.
| >>
| >> The app can loop through about 40 images, but on the second run, it
| >> raises the exception about have way through.
| >>
| >> FYI: the images are stored on an SD Card, are JPG format, and the
| >> device and os is a Dell Axim X5 with WM 2003.
| >>
| >> the error does _not_ occur in the emulator.
| >>
| >> S.S
| >>
| >>
| >> Private Sub ShowImage()
| >>
| >> On Error GoTo Trap
| >> 'Picture box width: 224, hieght: 232
| >> Me.picBox1.Width = 224
| >> Me.picBox1.Height = 232
| >> Me.picBox1.SizeMode = PictureBoxSizeMode.StretchImage
| >>
| >>
| >> Me.Text = strFilenames(nCount).ToString
| >>
| >> Dim strFullPath As String
| >> strFullPath = strRoot & "\" & strFilenames(nCount)
| >>
| >> If strFullPath = "" Then
| >> MsgBox("Error: path string empty!")
| >> Return
| >> End If
| >>
| >> Dim myBitMap As Bitmap
| >>
| >> If Not myBitMap Is Nothing Then
| >> myBitMap.Dispose()
| >> End If
| >>
| >> myBitMap = MakeBitMap(strFullPath)
| >>
| >> If myBitMap Is Nothing Then
| >> MsgBox("Error with: " & strFilenames(nCount))
| >> Return
| >> End If
| >>
| >> If myBitMap.Width < Me.picBox1.Width Then
| >>
| >> Else
| >> 'The aspect ratio of an image is the width / hieght
| >> 'get the aspect ratio of the image:
| >> Dim aspInt As Double
| >> aspInt = myBitMap.Width / myBitMap.Height
| >> Me.picBox1.Height = CInt(Me.picBox1.Width / aspInt)
| >> Me.picBox1.SizeMode = PictureBoxSizeMode.StretchImage
| >>
| >> End If
| >>
| >> 'Set the new bitmap to be the Image of the picture box:
| >> Me.picBox1.Image = myBitMap
| >>
| >> Exit Sub
| >>
| >> Trap:
| >> MsgBox("Error: " & Err.Description & " ..in ShowImage()")
| >> 'Resume Next
| >> Timer1.Enabled = False
| >>
| >> End Sub
| >>
| >>
| >> Private Function MakeBitMap(ByVal strPath As String) As Bitmap
| >>
| >> Try
| >> Dim MyBitmap As Bitmap
| >> If Not MyBitmap Is Nothing Then
| >> MyBitmap.Dispose()
| >> End If
| >>
| >> MyBitmap = New Bitmap(strPath) '<---error here
| >> Return MyBitmap
| >>
| >> Catch ex As Exception
| >> MsgBox("Error: " & ex.Message & " in MakeBitMap()")
| >> Return Nothing
| >> End Try
| >>
| >> End Function
| >>
| >>
| >>
| >> On Mon, 02 Feb 2004 16:43:34 +0100, Sarah Smith <[email protected]>
| >> wrote:
| >>
| >> >
| >> >Thank you both. I will try the steps you mentioned.
| >> >
| >> >I'll post back the results if you're interested.
| >> >
| >> >Thanks a lot.
| >> >
| >> >S.S
| >> >
| >> >On Sun, 1 Feb 2004 09:32:17 -0800, "Alex Feinman [MVP]"
| >> >
| >> >>Sara,
| >> >>
| >> >>Why don't you at least try the suggested steps? As it happens, nearly
| >100%
| >> >>of developers think their code is ok and there is something wrong
with
| >> >>OS/Library/Framework. After dust settles, only 99% of them have
proven
| >> >>themselves right.
| >> >>
| >> >>That said, there *are* bugs in CF, but to confirm it someone will
need
| >to
| >> >>see repro code
| >> >>
| >> >>| >> >>>
| >> >>> Hi Alex,
| >> >>>
| >> >>> thanks for your suggestions.
| >> >>>
| >> >>> I think the code is OK, and the error is a bug in the CF.
| >> >>>
| >> >>> I don't need to check the path (as you indicate below), because the
| >> >>> path has been verified earlier.
| >> >>>
| >> >>> As for using .Dispose() on the bitmap object ... I don't think
that is
| >> >>> usefull either because the bitmap is created inside a routine.
| >> >>>
| >> >>> Like this:
| >> >>>
| >> >>> Dim strFullPath As String
| >> >>> strFullPath = strRoot & "\" & strFilenames(nCount)
| >> >>>
| >> >>> If strFullPath = "" Then
| >> >>> MsgBox("Error: path string empty!")
| >> >>> Return
| >> >>> End If
| >> >>>
| >> >>> Dim myBitMap As Bitmap
| >> >>> myBitMap = MakeBitMap(strFullPath)
| >> >>>
| >> >>> If myBitMap Is Nothing Then
| >> >>> MsgBox("Error with: " & strFilenames(nCount))
| >> >>> Return
| >> >>> End If
| >> >>>
| >> >>> I moved the code in the MakeBitmap() function just to handle
debugging
| >> >>> a little better. So as you can see, each time the code is ready to
| >> >>> call the MakeBitMap() function, it creates a New Bitmap anyway.
| >> >>>
| >> >>> Or is the CF runtime doing something that is not normal?
| >> >>>
| >> >>> I always thought that when you enter a routine, local variables are
| >> >>> created, and then when the routine loses scope, and you are
returned
| >> >>> to the calling routine, the local variables are destroyed.
| >> >>>
| >> >>> Doesn't the CF runtime work this way?
| >> >>>
| >> >>> -SS
| >> >>>
| >> >>> On Sat, 31 Jan 2004 14:57:13 -0500, "Alex Yakhnin, MVP"
| >> >>>
| >> >>> >And also make sure that the file actually exists:
| >> >>> >
| >> >>> >If File.Exists(strPath) Then
| >> >>> > /'bla, bla bla
| >> >>> >End if
| >> >>>
| >> >>
| >>
| >
|
|
 
Sara,

I just realized that you code still succeptible to the same problem. You are
not disposing of the bitmap correctly. Consider replacing your code with
this:


Private Sub ShowImage()

On Error GoTo Trap
'Picture box width: 224, hieght: 232
Me.picBox1.Width = 224
Me.picBox1.Height = 232
Me.picBox1.SizeMode = PictureBoxSizeMode.StretchImage


Me.Text = strFilenames(nCount).ToString

Dim strFullPath As String
strFullPath = strRoot & "\" & strFilenames(nCount)

If strFullPath = "" Then
MsgBox("Error: path string empty!")
Return
End If

Dim myBitMap As Bitmap

' The reason for this acrobatics is that I'm not sure if Picturebox
' can handle correctly calling Dispose on its active bitmap
myBitMap = Me.picBox1
Me.picBox1 = Nothing

If Not myBitMap Is Nothing Then
myBitMap.Dispose()
myBitMap = Nothing
End If

Try
myBitMap = new Bitmap(strFullPath)
Catch ex As Exception
MsgBox("Error: " & ex.Message & " in MakeBitMap()")
Return
End Try

If myBitMap.Width < Me.picBox1.Width Then

Else
'The aspect ratio of an image is the width / hieght
'get the aspect ratio of the image:
Dim aspInt As Double
aspInt = myBitMap.Width / myBitMap.Height
Me.picBox1.Height = CInt(Me.picBox1.Width / aspInt)
Me.picBox1.SizeMode = PictureBoxSizeMode.StretchImage

End If

'Set the new bitmap to be the Image of the picture box:
Me.picBox1.Image = myBitMap

Exit Sub

Trap:
MsgBox("Error: " & Err.Description & " ..in ShowImage()")
'Resume Next
Timer1.Enabled = False

End Sub
 
Bingo!

Sergiy's suggestion did the trick!

Adding this code ...

If Not (Me.picBox1.Image Is Nothing) Then
Me.picBox1.Image.Dispose()
End If

Me.picBox1.Image = myBitMap

.... seems to have solved the problem.

Thank you very much for your help. You've restored my faith!

You guys have been great.

S.S
 
Sarah,

I'm glad that I was able to help you.
Please let me know if you have any other questions.

Best regards,
Sergiy.

This posting is provided "AS IS" with no warranties, and confers no rights.
--------------------
| From: Sarah Smith <[email protected]>
| Subject: Re: buggy activity in compact .net app
| Date: Tue, 03 Feb 2004 22:29:24 +0100
| Message-ID: <[email protected]>
| References: <[email protected]>
<[email protected]>
<#[email protected]>
<[email protected]>
<[email protected]>
<[email protected]>
<[email protected]>
<[email protected]>
<[email protected]>
<#[email protected]>
| X-Newsreader: Forte Agent 1.91/32.564
| MIME-Version: 1.0
| Content-Type: text/plain; charset=us-ascii
| Content-Transfer-Encoding: 7bit
| Newsgroups: microsoft.public.dotnet.framework.compactframework
| NNTP-Posting-Host: 0x50c48e18.adsl-fixed.tele.dk 80.196.142.24
| Lines: 1
| Path:
cpmsftngxa07.phx.gbl!cpmsftngxa06.phx.gbl!TK2MSFTNGXA06.phx.gbl!TK2MSFTNGXA0
5.phx.gbl!TK2MSFTNGP08.phx.gbl!TK2MSFTNGP09.phx.gbl
| Xref: cpmsftngxa07.phx.gbl
microsoft.public.dotnet.framework.compactframework:44762
| X-Tomcat-NG: microsoft.public.dotnet.framework.compactframework
|
|
| Bingo!
|
| Sergiy's suggestion did the trick!
|
| Adding this code ...
|
| If Not (Me.picBox1.Image Is Nothing) Then
| Me.picBox1.Image.Dispose()
| End If
|
| Me.picBox1.Image = myBitMap
|
| ... seems to have solved the problem.
|
| Thank you very much for your help. You've restored my faith!
|
| You guys have been great.
|
| S.S
|
|
|
| On Tue, 03 Feb 2004 00:36:59 GMT, (e-mail address removed) (Serg
| Kuryata [MS]) wrote:
|
| >Hello Sarah,
| >
| >Please could you answer a few questions so we could to narrow the
problem
| >down?
| >
| >When you first time load images, can you open all images from the list?
| >Does the problem occur only when you are trying to load the images
second
| >time.
| >
| >If an exception is thrown during the first loop, then please make sure
that
| >the image that failed to load can be opened on the device at all (i.e.
can
| >be opened from File Explorer by taping on the image). I'm asking to do
this
| >in order to make sure that format of the image is supported by the OS.
If
| >it is not, then the .NET Compact Framework will not be able to load it.
| >
| >Also looking at your ShowImage() method, I noticed that the bitmap that
is
| >assigned to the picturebox is never disposed. This will result in a
| >situation, when the device does not have enough memory to load another
| >image. Please try to change you code as the following:
| >
| >'Set the new bitmap to be the Image of the picture box:
| >If Not (Me.picBox1.Image Is Nothing) Then // add this code
| > Me.picBox1.Image.Dispose() // add this code
| >End If // add this code
| >Me.picBox1.Image = myBitMap
| >
| >
| >I hope this helps.
| >
| >Best regards,
| >Sergiy.
| >
| >
| >This posting is provided "AS IS" with no warranties, and confers no
rights.
| >--------------------
| >| From: Sarah Smith <[email protected]>
| >| Subject: Re: buggy activity in compact .net app
| >| Date: Mon, 02 Feb 2004 20:12:53 +0100
| >| Message-ID: <[email protected]>
| >| References: <[email protected]>
| ><[email protected]>
| ><#[email protected]>
| ><[email protected]>
| ><[email protected]>
| ><[email protected]>
| ><[email protected]>
| ><[email protected]>
| >| X-Newsreader: Forte Agent 1.91/32.564
| >| MIME-Version: 1.0
| >| Content-Type: text/plain; charset=us-ascii
| >| Content-Transfer-Encoding: 7bit
| >| Newsgroups: microsoft.public.dotnet.framework.compactframework
| >| NNTP-Posting-Host: 0x50c48e18.adsl-fixed.tele.dk 80.196.142.24
| >| Lines: 1
| >| Path:
|
 
Back
Top