Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

I'm making a particle engine so I develop a texture programatically and I want to display it in a Windows Form picture box. So I create the Texture2D which goes fine. Then I use this code to convert from a Texture2D to an Image for the picture box.

    public static System.Drawing.Image Texture2Image(Texture2D texture)
    {
        if (texture.IsDisposed)
        {
            return null;
        }

        MemoryStream memoryStream = new MemoryStream();

        texture.SaveAsPng(memoryStream, texture.Width, texture.Height);

        memoryStream.Seek(0, SeekOrigin.Begin);

        System.Drawing.Image image = System.Drawing.Bitmap.FromStream(memoryStream);

        memoryStream.Close();
        return image;
    }

I get the error at the texture.SaveAsPng(...). It says 'Cannot access a disposed object. Object name: 'Texture2D'.'
But as you can see, I just checked to make sure it wasn't disposed. I looked at the Locals info which also says the IsDisposed flag is false. No where in my code to I call texture.Dispose() or anything of the sort. I have no idea where this error is coming from. Any help would be greatly appreciated, thanks in advance.

share|improve this question
1  
Sounds pretty localized. Have you used the debugger and looked at the variables when they get to the SaveAsPng line? It's likely you're not creating the texture2D correctly so you may want to show us how you're doing that. But first, use the debugger and break on the SaveAsPng line and check out what texture looks like. I'm voting to close as too localized. –  Byte56 Jan 11 '13 at 15:38
1  
Additionally: (1) it's possible the object could be disposed from another thread between the check and the call to save, (2) SaveAsPng could be throwing an exception related to the disposal of something other than your texture (if it makes a temporary or copy or something?) –  Josh Petrie Jan 11 '13 at 16:15
    
Everything looks pretty normal for the texture. Plug I have already successfully drawn it to the screen at this point. This is kind of how things happen –  Jeff Jan 12 '13 at 1:11
    
Sorry, please dismiss that last sentence in previous comment. The problem occurs when I switch between which texture I want to draw. Each time I select the radio button that switches between textures, it sets a picture box to that texture. I only get the error after I deselect a texture, then reselect it. I think you're right that is has something to do with the texture because when I create a new texture to send to that method, it returns fine. I'll keep fishing around. Thanks guys. –  Jeff Jan 12 '13 at 1:19
2  
Sorry that people have been downvoting this and voting to close this. It's actually a legitimate question and there is a legitimate explanation. Yes it is a weird scenario - but it certainly can arise in some circumstances (like this one) - and people deserve to have some information about what's going on. I'm writing up an answer now... –  Andrew Russell Jan 12 '13 at 13:05

1 Answer 1

This is a bit of an oddity in the way XNA works - you could even call it a bug in XNA.

Basically there are two ways that Texture2D can decide that it has been "disposed":

First of all, there's the normal, managed way - when you call Dispose - that sets the IsDisposed flag and also unloads the native texture.

And then there's the wacky, native, internal, DirectX, magic way. Basically when the graphics device is "lost" (for example: the user minimises the window, or locks their session) the native objects that back textures (and other GraphicsResources) are invalidated. XNA clears them out and will attempt to recreate them when the graphics device is available again. It is possible for this recreation to fail - or you could be trying your operation while the device is lost, before they are recreated.

The bug in XNA is that operations on Texture2D check for the existence of the native texture, throwing ObjectDisposedException if it is not available. However this second way of losing the native texture does not set the IsDisposed flag!

(While it is arguably the wrong exception type, there's not much XNA can do in this case other than throw an exception - so it's not really a major bug. I can see why the XNA team might have not put in the effort to differentiate between the two cases.)

So, it's likely that the device your texture is on has been lost when you attempt to save it. If it's not something expected (like a minimised window) - and given that you're working with System.Drawing - I wonder if you're messing about with the GraphicsDevice that the Texture2D is bound to?

share|improve this answer
    
Well the problem arises when I try to access a texture I previously created after I create a new Texture2D. I do call Texture2D tex = new Texture2D(Game1.graphics.GraphicsDevice, 2*radius, 2*radius); to create the texture. So based on your response, do you suppose that the second time I call this, it erases the Texture I created the first time? Either way, I've got a workaround. Thank you very much for your detailed response and approval of this question. –  Jeff Jan 13 '13 at 15:13
    
I cannot think of any reasonable scenario where creating a texture would cause another texture to go missing, unless there is other code or a user action in between that causes the GraphicsDevice to be reset. One thought would be to hook its events, like Disposing and DeviceResetting, to see if that is the case. –  Andrew Russell Jan 14 '13 at 13:25

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.