I have an application I have been buidling for awhile and have finally finished the first draft of it (it's a screensaver). Anyway, during my countless hours of testing never once did I see an error this error I am getting now.

The error I am getting only occurs when the application is not running in Debugging mode. The error is as follows

"System.ArgumentException: Parameter is not valid.
at System.Drawing.Image.get_Width()"

And here's the code t's refereing to

public static Image ResizeCenter (Image value, int MaxWidth, int MaxHeight) //just like above, except this centers the image
{
    lock (ImageCenterLock)
    {
        bool WidthLarger = false; //notes if we resized because the width was greater then the height

        decimal NewHeight = 0;
        decimal NewWidth = 0;

        if (((decimal) MaxWidth / (decimal) value.Width) < ((decimal) MaxHeight / (decimal) value.Height)) //if the height difference is greater then the width (landscape)
        {
            WidthLarger = false;

            NewWidth = (((decimal) value.Width) * ((decimal) MaxWidth / value.Width)); //resize to the Width
            NewHeight = (((decimal) value.Height) * ((decimal) MaxWidth / value.Width));
        }
        else //width difference is greater then height (portrait)
        {
            WidthLarger = true;

            NewWidth = (((decimal) value.Width) * ((decimal) MaxHeight / (decimal) value.Height)); //resize to the Height
            NewHeight = (((decimal) value.Height) * ((decimal) MaxHeight / (decimal) value.Height));
        }

        Image TempImage = new Bitmap((int) Math.Floor((double) MaxWidth), (int) Math.Floor((double) MaxHeight)); //creates a image to the max size (that we then center in)

        using (Graphics graphicsHandle = Graphics.FromImage(TempImage)) //resizes the image
        {
            graphicsHandle.InterpolationMode = InterpolationMode.HighQualityBicubic;
            graphicsHandle.PixelOffsetMode = PixelOffsetMode.HighQuality;

            if (WidthLarger == true) //center the x-axis
            {
                graphicsHandle.DrawImage(value, ((int) ((MaxWidth - NewWidth) / 2)), 0, ((int) Math.Floor(NewWidth)), ((int) Math.Floor(NewHeight)));
            }
            else //center the y-axis
            {
                graphicsHandle.DrawImage(value, 0, ((int) ((MaxHeight - NewHeight) / 2)), ((int) Math.Floor(NewWidth)), ((int) Math.Floor(NewHeight)));
            }
        }

        value.Dispose(); //clear out the passed in image (seems to drastically reduce memory usage)

        return TempImage;
    }
}

Now here's the thing. If I were to comment out that value.Dispose();, the errors go away. The errors occur predicatably. They throw on the 2nd image, 7th, 14th, ext. Again this has no problem running in debugging mode, but the minute I run it without debugging I have a problem. I need to dispose of those images or else I get a nasty leak that shoots my resources up to GBs.

(Also, the value passed in is tied to a UserControl as a value you can get/set, and on return is plug into a PictureBox).

Any help would be greatly apprecaited. These images have become more and more headaches as they insist on referencing so much and chew up resources.

Recommended Answers

All 7 Replies

You haven't show your declaration for "ImageCenterLock". I haven't used lock, but you should only maintain your lock as long as you need it. I'm not familiar with the implementation of lock in C#, but I believe your issue may be because you are returning before releasing the lock.

return

"The return statement terminates execution of the method in which it appears and returns control to the calling method. It can also return an optional value. If the method is a void type, the return statement can be omitted.

If the return statement is inside a try block, the finally block, if one exists, will be executed before control returns to the calling method."

Try commenting out value.Dispose(); and moving the closing bracket for your lock before the return statement.

       //value.Dispose(); //clear out the passed in image (seems to drastically reduce memory usage)

    }//release lock

    return TempImage;
}//ResizeCenter

Note: In my limited research, I couldn't find an example of "lock" being used in a method that returns a value. It may be possible that if you return before releasing the lock, the lock may be maintained and result in deadlocking. Which would explain the high memory usage.

I believe that your overall memory issues are probably due to the manner in which you use locking. The rest of your code would need to be examined. Unfortunately, I'm not familiar with locking in C#.

The Locks are probably not the problems, otherwise, these if the lock was never relased the program would have grid locked (have had thta happen before when messing with locks ... the application waits at that spot till the lock is freeded).

As you know, locks are used to protect critical regions when working with multi-threading, to prevent a clash. Since the function is static, it's already in memory (and I believe, is only initalized once, meaning multiple threads could access it at the same time).

I actually did a little experimenting, using clone and what not, and was able to keep the disposes. I Believe I fixed it, but what I would like to know is why the heck this worked find evertime when Debugging, but on its own, it blows errors (that from what I can tell, relate to null error)

...it could be related to using a "using" statement.

using Statement (C# Reference)

File and Font are examples of managed types that access unmanaged resources (in this case file handles and device contexts). There are many other kinds of unmanaged resources and class library types that encapsulate them. All such types must implement the IDisposable interface.

You can instantiate the resource object and then pass the variable to the using statement, but this is not a best practice. In this case, the object remains in scope after control leaves the using block even though it will probably no longer have access to its unmanaged resources. In other words, it will no longer be fully initialized. If you try to use the object outside the using block, you risk causing an exception to be thrown. For this reason, it is generally better to instantiate the object in the using statement and limit its scope to the using block.

Image.Dispose
Calling the Dispose method allows the resources used by this Image to be reallocated for other purposes.

Call Dispose when you are finished using the Image. The Dispose method leaves the Image in an unusable state. After calling Dispose, you must release all references to the Image so the garbage collector can reclaim the memory that the Image was occupying. For more information, see Cleaning Up Unmanaged Resources and Implementing a Dispose Method.

Always call Dispose before you release your last reference to the Image. Otherwise, the resources it is using will not be freed until the garbage collector calls the Image object's Finalize method.

Using Objects That Implement IDisposable

Note that the code...checks that the object that implements IDisposable isn't null before it calls the Dispose method. Failure to do this can result in a NullReferenceException exception at run time...

I didn't notice exception handling in this method (try-catch-finally). The following may be of use:

C# - Dealing with Unhandled Exceptions

You might try moving value.Dispose(); inside the closing bracket of the using statement:

using (Graphics graphicsHandle = Graphics.FromImage(TempImage))
{
                          ...

    if (value != null)
    {
        value.Dispose();
    }//if
}//end using

Hi AoD, I think it's because you're disposing of something that's being passed to your method.

This is pretty much a big no-no. You don't know what happens to that object outside of the method you've written, disposing of it could present problems.

Whilst I understand that calling dispose is freeing memory, you need to dispose of it further away. Essentially, the thing creating the object is also responsible for disposing of it (Unless you know for a fact that you should be disposing it. ie In the Dispose call or "OnUnload" etc.)

There are some things we need to know about how your method is used before making a committed decision however. How is that method called (what calls it and when), is the return signature important (your image is passed by reference, the caller may be expecting the reference to change).

I believe (personally) the mistake made here is that you're disposing in a location that doesn't indicate it's being disposed and as such has no responsibility for disposing (this method did not create the reference)

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.