Freigeben über


A penny for your thoughts on Windows Phone 7 tombstoning

One piece of feedback we hear from Windows Phone developers is that "tombstoning is hard," but there are many ways of interpreting that statement and we'd like to understand it more. We have some theories about what might be hard, but I don't want to skew any results by mentioning them here.

If you have an opinion on tombstoning in Windows Phone 7 - good or bad - please leave a comment and be as detailed as you can in the reply so we can better understand the feedback.

Thanks!

P.S. I'm joking about the penny.

Comments

  • Anonymous
    March 06, 2011
    What's tombstoning?

  • Anonymous
    March 06, 2011
    Steve, "tombstoning" in this case refers to the application lifecycle of Windows Phone apps... I guess I should add that to the post! Thanks!

  • Anonymous
    March 06, 2011
    To me what makes it hard it not so much the tombstoning process - it's more the fact that I have to do it. Example: I want to grab a picture with the camera. This leaves the app, and I would have to save all settings and state of the app. but here's what gets weird: Some things automatically gets restored: For instance the current page, or often parts of the state of a page (but far from everything). I would have to save a bunch of data to IsolatedStorage, although not everything. I usually just dump my entire app-model, so that's not really such a big issue to me, but still... I had to go through a lot to get that set up in the first place. Add to that that there are things I can't just "dump" to IsolatedStorage, because not everything is serializable. I get that when I leave an app I should save stuff, for instance remember username/passwords etc. I don't get why I need to do all this if I briefly leave the app and come back using back button. (ie answer a call, use camera, check my calendar etc). It should just pause the app, and not try to serialize state or anything. Basically I think I shouldn't have to do ANYTHING until my app is about to get completely killed (and in this case only if I want to remmeber user settings etc). Having these two "modes" , ie "full" shutdown and "temporary" shutdown is confusing. Why are there two? I say: Simplify this pattern. Another confusing thing (and an often reason for bugs - even in Microsofts own controls) is when I leave an app, and quickly hit the back button (happens a lot because search button is too easy to hit). Apparently when this happens, it's going into some "weird" kind of half-way tombstone/restore process. Its hard to test and can give some really hard to track down and hard to reproduce bugs. Again: Don't give me all these different kind of states an app can be in. Simpllify, simplify, simplify.

  • Anonymous
    March 06, 2011
    Tombstoning isn't necessarily 'hard', but it's more complicated than it needs to be. I guess it's works a bit like ASP.NET session state, with manual resumption, but it's not a stateless web app so app architecture doesn't fit that model. Perhaps something like a [Persist] attribute would be helpful?

  • Anonymous
    March 06, 2011
    Hey Peter. I haven't found tombstoning particularly hard. Verbose perhaps, but not hard. If developers are finding tombtsoning hard or verbose, I'd point them at the excellent Caliburn Micro MVVM framework (Bing it), which handles persistence for you through a simple decorator on a View Model property.

  • Anonymous
    March 06, 2011
    I don't think that it's too hard, but there are many pain points:

  1. Knowing about this, as most developers will start without implementing tombstoning (in simpler apps you will not notice that it's missing)
  2. Actual implementation can be a bit messy - partially this should be implemented in App.xaml.cs and partially in pages OnNavigate* method
  3. App having two startup workflows (for starting and re-activating) makes developement slower, and frameworks like CaliburnMicro help simplify this
  4. Increased cost of testing these two paths for every page
  • Anonymous
    March 06, 2011
    I don't mind the tombstoning so much as having better support for it. There should be a good way to serialize out the state of a ViewModel... e.g. a viewmodel base class that has support plus automatic save and load functions to isolated storage. There should be an "after loaded" event because doing anything of interested in the Loaded event is not really advisable... winforms added a "Shown" event, perhaps that could be added.   jfoscoding.blogspot.com/.../beware-loaded-event.html There should also be a better way to test the Trial apis because the show marketplace task api tombstones your app and you need to be able to test your app when it has been resurrected after someone has bought it.

  • Anonymous
    March 06, 2011
    The comment has been removed

  • Anonymous
    March 06, 2011
    I generally like it. What I think throws people off (and I didn't really understand it myself until your post in the App Hub forums earlier) is that a page's constructors might never run when coming back to it. Unless you read the documentation really, really closely, it's very easy to miss that. I also think that the structuring itself leads to confusion about that. There's Launching, Closing, Activated, and Deactivated. Deactivated is not synonymous with tombstoning though it's very easy to conclude that deactivated == tombstoning. Instead tombstoning is (if I'm reading it correctly) something that can (but does not have to) happen while an application is deactivated. If it is tombstoned then the constructors run and Activated is called. If not then the constructors do not run and Activated is called. So in effect there are two different kinds of "Activated" - one with constructors and one without. Only you never actually know which one you're in and the kind that's most likely to cause problems (not tombstoned and thus the constructors don't run (and I assume that includes the page constructors for the particular page the user was on)) is also the kind that's less common and can only be triggered and thus only be tested through, e.g., jamming start and back in rapid succession. I think it would probably serve everyone better if the constructors always ran, though I suppose that there are performance implications that weigh against that. And then once you do know that there's a special activated path sans constructors, the question then becomes what data dies on deactivated and what survives? Are value types reset to their default values? Do event handlers remain intact? Does a Silverlight page automatically undergo a measurement and layout cycle when returning or does that need to be triggered again (and what effect, if any, does that have on any data-binding)? When tombstoning doesn't occur Deactivated happens but the Loaded even never fires (since the constructor never runs). This might be a source of many problems that people face since, absent lazy loading, the Loaded event is where most developers who have learned enough that they avoid putting complex, time-consuming operations like I/O into the page constructor would in turn put it into the Loaded event. Then there's the fact that it's quite simple to produce an infinite "Resuming..." loop. Create a Silverlight for Windows Phone 7 Application. Build it. Run it. Press Start and then Back in rapid succession. Repeat this process several times and you are certain to eventually watch the emulator/device try to resume while Visual Studio tells you "The program '[205127770] taskhost.exe: Managed' has exited with code 0 (0x0)." and reverts to non-debugging mode. But the phone (or emulator) will continue to insist that it's resuming something and will keep doing that ad infinitum unless you either press Start or Search or else power off the phone.by holding the power button down until it shuts off. I had an application resuming in the emulator for the past 5 minutes or so. At this point the indefinite progress bar has actually stopped animating and the five dots are just sitting in the middle of the window. Pressing Start and then Back again caused it to resume (so I assume that it had just gone into the emulator's equivalent of the lock screen - having just left it sit for another ~5 minutes it did the same thing though this time only one of the dots was visible at the left). This is essentially a vanilla, from the "Windows Phone Application" template app; the only thing I added was a Loaded event handler to the MainPage and three System.Diagnostic.Debug.WriteLine calls (one each in App.Application_Activated, App.Application_Deactivated, and MainPage.PhoneApplicationPage_Loaded just to confirm that Loaded didn't fire on a rapid Start-Back cycle). This is using the emulator image from the January tools update though I had seen the same behavior in the RTM emulator and see it on my phone itself too (an LG-C900 (Quantum) which has not yet had the pre-NoDo update). Between Loaded only firing sometimes and the infinite resuming bug, I can see it being easy to get frustrated with it. I generally think it's a nice structure, though if it could be tweaked somehow to let developers know whether or not the constructor and Loaded and any other events that happen during the page construction process run  that would be nice. It'd be interesting to me to see if there's something common to people who dislike it the most. I don't really use MVVM, for instance, and tend to rely on code-behind a lot more than XAML-based data binding. I know I should use Blend more and that it's a really nice tool, but I think I've started it less than a dozen times and have never done anything of substance with it. Maybe there's no correlation, but it's worth investigating. Anyway, keep up the great work! It's been nice seeing you posting on the forums - I've already learned several things from your posts there (e.g. that the constructors don't always run and thus that Loaded doesn't always run).

  • Anonymous
    March 06, 2011
    The comment has been removed

  • Anonymous
    March 06, 2011
    Peter, I believe half the challenge here is the way that it is explained/taught to developers. Most of the time I hear tombstoning explained in terms of Activated and Deactivated events. This leads developers to put logic into these events to save state etc. When I present on tombstoning I focus on the OnNavigatedTo and OnNavigatingFrom methods and get developers to save and restore page state in these methods. If they do this it solves 90% of the tombstoning challenge.

  • Anonymous
    March 06, 2011
    I don't find it hard to do - what kind of problems are you hearing about?

  • Anonymous
    March 06, 2011
    From my experience if you use MVVM light and serialize the ViewModels with Mike Talbot's serializer, tombstoning is a piece of cake. However if you code the quick and dirty way with events "hardwired" to the .xaml.cs and no proper separation of concerns, it quickly becomes a mess and difficult to make it work well even for simple apps. This may not be so bad as it forces the developer to properly structure the app, but I can see the difficulty for someone in the learning phase. Regardless, one thing I've found it difficult is handling textbox focus: it's rather hard to restore focus to the proper element after activation (so that the keyboard is displayed again). It's a detail and I never failed certification because of this, but I've often faced this situation.

  • Anonymous
    March 06, 2011
    From what I experimented, the major difficulty to handle tombstoning is the break in the application's flow. Your application is resumed on the last page, it can be any page of any process of the application. Yet, all the vars (which are supposed to be set in the previous steps of the process) are reset. It forces the developers to learn how to handle application's state in a more global way, while WPF and Silverlight are designed to be used on a more "page centric" way.

  • Anonymous
    March 06, 2011
    I don't think it is hard. It just happens that you always forget one thing or the other and break everything :D But I think tombstoning is something that only complex applications should have to handle themselves. I wonder why DataContract isn't just an opt-out model and tombstoning would just save the app object and the current page.

  • Anonymous
    March 06, 2011
    Hi, I've built a couple of apps for windows phone 7, at work and at home, and my experience with tombstoning is this:

  1. If you consider tombstoning from the start and during the design of the application it's not rocket science, and is in fact pretty simple
  2. If you've completely ignored tombstoning while building your app, and your customer asks for tombstoning support later, then,as Josh Topolsky will put it, it's a nightmarish hellride Tombstoning can be difficult to grasp at first, and I felt there are a few inconsistencies with the implementation. For e.g consider this
  • my app starts and Mainpage.xaml is showing
  • user navigates to SecondPage.xaml
  • now user presses the start button and then presses the back button to navigate back to SecondPage.xaml In this scenario there is no way to know if the constructor of SecondPage.xaml will be called or not. If the user presses the back button too soon, before the app is actually "tombstoned", the constructor will not be called. But if the back button is pressed after a long time, then the constructor gets called. This, of course, is trivial to solve by using flags etc, but I feel it makes the handling of page local data messy. Prabhu www.techtwaddle.net
  • Anonymous
    March 06, 2011
  1. I don't see any good solution for saving unrelated data during tombstoning. For example I want to save texts from text boxes, check boxes status and other states of UI elements on current app page, but also I want to save some "model" data unrelated to current page. Putting it all in single dictionary is not elegant solution IMHO, not everything fits into key-value pair paradigm.
  2. For some reason tombstoning does not allow you to save images and throwing exception. Why not? This is especially problematic with downloaded images (think avatars in twitter app). This means I need to use some other mechanism for storing transient images (probably Isolated Storage API) leading to additional complexity - some data is stored in dictionary and some on isolated storage. I'd love to see more "real world" examplestutorials on tombstoning. Currently there aren't any complete solutions to this, but only few disconnected code samples that give you basic understanding, but are not that helpfull in actual development, leaving a lot to be figured out by programmers. Just my 0.02$ Hope this helps -Dennis
  • Anonymous
    March 06, 2011
    In my experience, tombstoning is hard for two main reasons:
  1. It requires some fastidious code to save and restore the application's transient state. This is especially cumbersome for page transient states for which the SDK does not always provide easy-to-use APIs (TextBoxes with bindings, ListBox scrolling offsets, DataTemplates) or, in some cases, no API at all (Panorama current item).
  2. It requires all pages of an application to be independent of each other, because only the current page is reinstantiated when the navigation stack is restored upon activation. It's not difficult to handle once you understand the constraints and it leads to better code architecture, yet this is a counterintuitive requirement. Another minor (yet confusing!) reason is that an application sometimes won't be tombstoned at all between deactivation and reactivation, like when the user presses the Home button followed immediately by the Back button.
  • Anonymous
    March 06, 2011
    When I've asked people it basically comes down to the fact that it requires more than drag and drop. :(

  • Anonymous
    March 06, 2011
    I think it's pretty hard to tombstone correctly. Most apps I downloaded/bought have tombstoning issues. I don't know what Apple did to solve this issue is iOS, but it looks like their system works better. Also currently it isn't always clear when tombstoning is happening. Sometimes WP7 saves the state by itself in memory and other times you have to do it yourself. Of course this behaviour is documented, but it would be better to have a consistent approach, IMHO.

  • Anonymous
    March 07, 2011
    I really think tombstoning should be automatic, but also allow us to turn this feature off if we would like a custom implementation.

  • Anonymous
    March 07, 2011
    Thank Peter.  It is actually tricky coming up with a decent answer here.  One of the hard things about Tombstoning is that it exists, and needs to be accounted for.  Having to deal with the nuances of tracking state of possibly every part of your application at nearly every moment and account for any random termination eventuality is quite a shift from development where termination is a (fairly) fixed ocurrence. Outside of that broad swath, a few specific things jump to mind:

  • The Chooser Model is inherently broken when it comes to Tombstoning.  The fact that the Completed event fires before the Page's OnNavigatedTo method - meaning that PageState is inaccessible to Choosers - is painful.  Yes, the Choosers have been optimized to not tombstone, unless someone brings up the Start page while in a Chooser and then hits the back button...so from a dev standpoint, there is no optimization - it is only a performance enhancement.  As a solid case, try to type some text into a textbox on a page, then give the user a button to send that text.  On button press, bring up a mail address chooser, and then feed that directly into a send-mail launcher.  You're stuck either using the App State  dictionary or ISO storage.

  • The App State Dictionary has a maximum size limit, but it isn't documented.

  • Exceeding size limits in the Page Dictionary throws a COMException, instead of something more specific

  • It might be nice for pages to participate more directly in Tommbstoning - through direct overridable methods.

  • The Pivot Control has a big that makes setting the "last used page" difficult when restoring from Tombstoning. For even more fun, see Jeff Prosise's 4-part writeup on Tombstoning -  www.wintellect.com/.../real-world-tombstoning-in-silverlight-for-windows-phone-part-4.aspx (This is Pt 4, and has links to Pts 1- 3) There's an entry on MSDN offering guidance for how to restore state to controls (less of an issue when MVVM gets involved, but when exactly are you over-architecting a micro/phone-app?)  I am having trouble locating the prceise URL, but will update when I locate it.  The volume of work identified in that article alone will give you one heck of a start. Thanks for asking the question.  I hope this and subsequent answers help. --John Garland

  • Anonymous
    March 07, 2011
    I think that tombstoning is a given "fact" that needs to be considered when creating apps, however, it is not ideal for any kind of app unfortunately. In particular, games that have to load some content into memory before operating, will never load smoothy and will give the user a pretty bad experience.

  • Anonymous
    March 07, 2011
    The comment has been removed

  • Anonymous
    March 10, 2011
    my 2 cents :) When you are building an app especially one with lot of pages (especially enterprise apps), tombstone handling increases your development time significantly. A lot of effort is spent in testing all pages even when you make simple code changes. It is also a real barrier to get apps certified. ( One day I will write a book about app certification and there is certainly a chapter for tombstoning ) I am sure there are folks who can be sure that it is trivial, but again, if you are not building one page apps, this increases dev and certification duration.

  • Anonymous
    March 23, 2011
    I agree that tombstoning should just happen.  It gets complicated when there are panos and pivots and user controls involved.  It would be great if it could handle user controls.  For example on a pivot where each pane is a user control.  When a pane is not visible I would like to store it, and all non visible user control / panes to current state, until it is visible again.  That helps keep the memory managable. But when tombstoning comes along it can't handle the temp stored user controls.

  • Anonymous
    April 12, 2011
    In my case it is not hard but is very boring and time consuming work. If I can focus more onto features of my app instead of tracking all the silly bugs of tombstoning, the joy of wp7 development is getting better. Android, iPhone have similar kinds of concept but WebOs programming has no multitasking special stuffs. I believe if we had developed DESKTOP PROGRAM like this way - i mean tombstoning - fewer app remains as quality app. Thanks.