WPF - NavigationService memory troubles - wpf

I needed to write an application for kiosk terminal and I choose WPF for this, because I need single window application. Implementation is simple - NavigationWindow and set of Pages, that uses in NavigationService.Navigate() method.
During using the application, I saw that it freezes, consuming large amount of memory. I found that when content is navigated to, NavigationService records the navigation as an entry in navigation history. I started to clean up history by using NavigationService.RemoveBackEntry() method.
Yes - history is cleared, but page's finallizers doesn't call. Pages are still being in memory and finallizers call only when the application is closed. I can just go from one page to another and then go back several times - application will consume about 150-200 Mb (starts from 5-6 Mb).
I checked the application with memory profiler and found that used memory doesn't increased - its about 5-8 Mb, but working set consume large amount of memory.
So I found a way to clear working set, but I didn't leave a thought that it is a wrong way. Solution must be more easier.
Documentation says that NavigationService does not store an instance of a content object in navigation history. Instead, NavigationService creates a new instance of the content object each time it is navigated to by using navigation history. This behavior is designed to avoid excessive memory consumption. But as I see it doesn't work this way.
I was thought that this behavior works only when NavigationService use URI for navigation (I call Navigate(new MyPage()) for navigating), but is doesn't work even with URI - pages instances still being in memory even if I clear the history journal.
So here is the questions:
1) Anyone else faced a similar problem?
2) Is that correct and best way to use NavigationWindow to build a single-window application?

Related

Best strategy for a magazine app

I'm developing a Magazine app and trying to find the best strategy to optimize performance and stability. The app should be able to handle +100 pages and expect users to swipe between them fast and smoothly.
With all this in mind, this is what I've tried so far.
The basic structure would be using tabs, with tabs bar hidden, to allow user swipe. Since loading + 100 tabs with huge images would be a mistake, I always mantain three tabs: the current page, the previous and the following. With a selection listener I change the positions accordingly.
The way I load and dispose images as selection changes is the big deal here. The app downloads the images from Internet and cache them in FileSystemStorage. Those images are 768 x 1024. This is what I've tried with different luck:
Simply retrieve the images from FileSystem everytime a new page is requested:
if (FileSystemStorage.getInstance().exists(rutaImagen)) {
try {
int size = (int) FileSystemStorage.getInstance().getLength(rutaImagen);
EncodedImage imagenPubli = EncodedImage.create(FileSystemStorage.getInstance().openInputStream(rutaImagen), size);
} catch(IOException io) {
}
}
This has proven to be inefficient and risky in terms of memory usage. My iPad mini launch frequent low memory warnings, and end up killed by jetsam after a little while.
Store the images in a WeakHashMap, so Images don't need to be constantly loaded form FileSystemStorage, which seems to be the cause of problems and too expensive. Only if they are garbage collected, the first method comes in action.
This solution perfoms better, and the memory warnings are dramatically reduced, but are still there. After stressing hard the app, 15 or 20 minutes later jetsam jumps in and kill the app.
Similar approach: instead of WeakHashMap, I have tried CacheMap. This has been the best solution for me so far. I have to push hard to see some memory warnings once in a while, and no crash so far. Still not enterily happy though, because I believe I should not see any memory warnings at all.
I talk about iOS only here because the app performs well on Android whatever method I use, and I have never got any Out of Memory there.
What do you think? Am I in the right path? Would you guys use a different approach?
Thanks
I believe that you should use the "let-it-be-done" approach. So far you have tried to code everything yourself, while codenameOne has many optimized way of doing it. The easiest way would be to use a MultiList, which will display your images (by using an UrlImage). The UrlImage will allow codenameone to handle the caching and else. Basically, the image will be loaded when viewed and placed in cache afterwards.
It's unclear from the question where the magazine page is just an image. If so I would suggest using the ImageViewer class as it was designed exactly with the use case of an infinite list of large images to swipe and zoom thru.
The general strategy with the Tabs seems like a good start if you need something more elaborate than images. If it doesn't perform well you can always substitute Tabs for something else.

WPF application not releasing memory on logout

I am working on a WPF application which doesnot seem to release all the memory when logged out of a screen. On start of app, there is a login screen where I enter userID/Pwd. It takes to a different screen(lets say WPF2). At this point, I am totally unloading the login screen(memory now is 70MB). WHen the WPF2 screen is loaded with dynamically memory goes upto 200MB. When the user logs out from WPF2, login screen loads again. AT this point, I am clearing all objects used in WPF2 in dispose method. But the memory is still 200MB not 70MB, and also when I login again it increases from there.
WHen the application is closed, all memory used is released.
I understand this is very application specific question, but any general ideas are highly appreciated.
Thanks
Items are not released from memory when an event handler is still attached to them, or when the application closes.
This sounds like you have some event handlers to clean up.
Hope this Helps,
You gave not enough information about how you get the memory values. I assume you looked in task manager? If you look only at task manager, you will probably not get the values you expect. Furthermore, memory releasing is not done in the moment a object is no more used. It is an asynchronous task done by the Garbage Collection. If you want to measure memory at a specific point of time, you probably should force GC to free memory before (but only for measurement, not for production code). Look at this thread to get a starting point about the different memory types.
Here you find a very good video, that gives a start to debug memory problems in WPF.
When you call Dispose()on a IDisposableyou can clear umanaged resources.
The GarbageCollector may not have collected WPF2 yet.

Silverlight: Clear unused memory on navigating to another page

My silverlight application has many pages and uses Navigation Service to navigate between pages. One of the pages fetches a large amount (~1G) of data from a web service. Since garbage collection is not happening automatically, I need to clear the memory allocated in that page when I go back to the previous page (Home page).
I tried overriding OnNavigatedFrom method and tried assigning object references to null and forcing a garbage collection by GC.Collect(). But the memory is not getting cleared. I noticed that if I refresh the Home Page, the memory comes down drastically. How to do memory clearance programatically.
Calling CG.Collect manually is not a good idea, and in any case GC.Collect does not help removing memory leak. Memory that can be free is free by the standard CG behaviour. Maybe looking for the reason that memory is not automatically free will evidentiate some bug somewhere.
You will need to spend a lot of time tracking the memory leak down and this can be a painful process. There are some good tools out there that can assist you.
See my previous post here: Silverlight 4 memory leaks
One way I've cleared the memory is to re-load the page, or to have the same app span across multiple asp.net pages...
So instead of navigating, it will unload the app (releasing all memory) and re-load the app. I know gurus will hate this short-sighted answer, but it's the only way I've effectively been able to have the memory dump.
An example would be say your app is in default.aspx and instead of navigating to something like default.aspx#control1, you put the same app in a new page like control1.aspx and navigate to control1.aspx#control1. Either that, or you can separate the app out into multiple apps to be loaded across multiple pages.
I've noticed huge gains from this.

Silverlight stop page closing before being saved

In the old days for WinForms, if your user was creating/editing some information in a DialogBox, it was easy to detect the Window closing and if the data was dirty, ask if they wanted to save.
My question is, how do you approach this scenario in Silverlight where everything seems to be done in UserControls, which have no obvious way of knowing when the page is closing, ie switching to another page within the Silverlight app would simply open a different UserControl without checking the previous UserControl needed saving.
There must be some standard way of achieving this?
If you need to ask the user a question about whether to save or not then you will need to handle this in the browser the onbeforeunload (whilst not a standard event it is supported by those browsers on which Silverlight is officially supported). It may be possible to set up a little javascript to call back into your application when onbeforeunload fires.
That said I'm not a fan of the "Are you sure, you want to lose all that work you've just done" type of question. "Of course I don't want lose it, save it already, as long as I can undo it later if necessary I'm happy".
You can handle the Application.Exit event to execute code on application shut down. Be warned that at this time the networking stack has already shut down so you can't send any messages from the Application.Exit. You cannot cancel the event.
+1 Michael. It is a current limitation of SL. You can however persist to isolated storage from the app exit event, would it be feasible in your app to check if dirty, and if so save to iso storage. Then next time your app loads you could load the dirty data from iso storage ready to carry on editing..?

Question About Silverlight and how the application is loaded

In Silverlight 3.0 we can now create applications with multiple pages using the navigation framework, My question is :
When we run the application does the whole application gets loaded up at once or it gets loaded up when we navigate to a particular page ?
This is probably important for those who want to create an application that gets loaded up very quickly, if everything is loaded up at the begining, the whole user experience might become like a nightmare as they have to wait a long time.
Thank you.
Mmm...
If the entire XAP is loaded check how is stored in browser cache.
On the other hand, you can perform partial loads as markti commented, how to define your views? use interfaces contract, so you can deferr the load the views to show on demand (main XAP loads application, plus interface assemblies, the you divide the views into several DLL's, maybe main page is loaded and the rest just loaded in background).
You can as well use isolated storage to cache that Dll's (then your application will read that Dll's from the local computer).
http://timheuer.com/blog/archive/2008/09/24/silverlight-isolated-storage-caching.aspx
The entire executing XAP is loaded into memory. This is less important because having the Pages defined is not the bulk of the work. The bulk of the work is when the Pages are constructed and then rendered. The Pages are not constructed/rendered until the Page is navigated to.
If your XAP starts to get bulky (causing the initial download to take some time) you can get around that problem by lazy loading XAPs or assemblies using WebClient.

Resources