ratishphilip / CompositionProToolkit

Collection of Helper classes and controls (using Win2d) for Windows.UI.Composition
MIT License
235 stars 29 forks source link

System.ObjectDisposedException: The object has been closed. #5

Closed Hanzalah-Adalan closed 8 years ago

Hanzalah-Adalan commented 8 years ago

Sir it's me again.. this time I got a strange runtime error.. There's a listview in my app's home page.. I loaded 50 items in the listview at a time which looks like this: prob 2

and as I scroll the listview up and down, my app crashed and throwed this nice little exception:

System.ObjectDisposedException: The object has been closed.

The given object has already been closed / disposed and may no longer be used.
   at Windows.UI.Composition.SpriteVisual.get_Brush()
   at CompositionProToolkit.Controls.CompositionImageFrame.<LoadImageAsync>b__123_1()
   at CompositionExpressionToolkit.CompositorExtensions.<>c__DisplayClass5_0.<CreateScopedBatch>b__0(Object s, CompositionBatchCompletedEventArgs ea)

The exception said it tried to dispose an object that is already disposed or to load the object that is has been disposed.. I don't know what object did it refer to.. perhaps you know better since this is your control. Regards

Hanzalah-Adalan commented 8 years ago

and it doesn't crash everytime I scroll up and down the listview.. sometimes it crashes sometimes it won't.. that's why I said it was a strange exception..

Hanzalah-Adalan commented 8 years ago

One thing for sure if I scroll too fast using the listview scrollbar (not using mouse wheel) all the way down to the bottom most of the listview item (which in my case the item at index 49), the app will crash and throw that exception

ratishphilip commented 8 years ago

@HanAnonymous Thanks for reporting this. I have identified the cause of the issue. It will be fixed in the next version.

ratishphilip commented 8 years ago

@HanAnonymous The crash issue is now fixed. Please install the latest NuGet package.

Hanzalah-Adalan commented 8 years ago

Thanks for your great effort!

naweed commented 8 years ago

Hi, Btw, I am on the latest version, and I also notice such issues (app crashing because device is lost or DeviceDispositionException) when I switch between pages multiple times.

naweed commented 8 years ago

To be specific, this is the error I get.

The GPU device instance has been suspended. Use GetDeviceRemovedReason to determine the appropriate action. (Exception from HRESULT: 0x887A0005)

Sometimes, I also get something like System.DeviceDispositionException at Microsoft.Graphics.Canvas... (will update when I see it next time).

ratishphilip commented 8 years ago

@naweed Thanks for the info. Which all objects (related to CompositionProToolkit) references are you having in your page? Are you disposing them correctly when the Page is unloaded? If they are not, then it might raise such an issue.

Can you step through your page's code (when you switch pages and return to the page raising the exception) and see which line of code is raising this exception?

naweed commented 8 years ago

Hi Ratish, I am using ImageFrame inside a gridview on the page.  I have not written any code for page unloaded. Also I noticed that the memory doesn't get released as I keep navigating from page to page, for all the pages where I have used this control.

Sent from BlueMail

On Sep 7, 2016, 15:46, at 15:46, Ratish Philip notifications@github.com wrote:

@naweed Thanks for the info. Which all objects (related to CompositionProToolkit) references are you having in your page? Are you disposing them correctly when the Page is unloaded? If they are not, then it might raise such an issue.

Can you step through your page's code (when you switch pages and return to the page raising the exception) and see which line of code is raising this exception?

You are receiving this because you were mentioned. Reply to this email directly or view it on GitHub: https://github.com/ratishphilip/CompositionProToolkit/issues/5#issuecomment-245269305

ratishphilip commented 8 years ago

ok. I will look into it.

naweed commented 8 years ago

Thanks. Plz let me know if you need anything from my side.

naweed commented 8 years ago

@ratishphilip Further to issue reported yesterday on memory leak (https://github.com/ratishphilip/CompositionProToolkit/issues/6), if I remove the ImageFrame and replace with regular image (code in the memory leak issue), I don't get the device error at all.

Hanzalah-Adalan commented 8 years ago

Lost Devices

When a device is lost, you traditionally need to recreate your graphics device and all of the resources you created with that device. XAML usually handles this for you, but you need to be aware of it when using the Composition APIs. When can a device be lost? It could be anything from a graphics driver update, to a device that is switching to a different GPU (like with the Surface Book or a laptop disconnecting from something like a Razer Core), or a set of incorrect calls to the GPU that puts it in a bad state and it needs to reset (we call this Timeout Detection and Recovery, otherwise known as TDR). To learn more about lost devices, check out this MSDN article. While it is not strictly required to handle a lost device, it is greatly recommended that your application is resilient to it. Otherwise when a user detaches their Surface Book from its base with a GPU, your application might lose all of its surfaces! So what do you have to do? If you use CompositionImageLoader you should be set. Just know that if you use LoadImageFromUri or LoadImageFromUriAsync, you’re not protected from a lost graphics device. The ImageLoader does have a DeviceReplacedEvent event you can listen to and redraw your surfaces if you want. However, there’s an even easier way, and that’s by using ManagedSurfaces. If you use CreateManagedSurface or CreateManagedSurfaceAsync and keep the object alive, you won’t have to worry about lost graphics devices (same goes for methods that create a TextSurface). ManagedSurface is the recommended way to go. One last thing about the ImageLoader, because it creates a graphics device you should try to only keep one around. Creating many of them can become expensive and waste memory. Store it somewhere where you can have good access to it and reuse it. That’s when the ImageLoader can do its best. The ImageLoader makes all of its drawing calls asynchronously (even with the non async methods, the surface creation is synchronous but the ImageLoader draws to it later on) and under a lock, so you shouldn’t have to worry too much about threading.

copy paste from: http://blog.robmikh.com/uwp/composition/2016/04/21/images-and-effects.html

I don't really understand this thing, but perhaps using IManagedSurface might help

ratishphilip commented 8 years ago

@Hanzalah-Adalan ImageFrame and ImageSurface handle lost devices too in a similar way.