WP7是不支持多任务的,但是提供了一个TombStone机制,这个机制,通俗来说,就是提供了5个坟墓给你,如果你要你的程序进入“后台”,那么就给你埋在那里,如果你要启用你的“后台”程序,就从坟墓里把程序挖出来,并且从内存中把相关数据加载到控件,简单来说就是借尸还魂。
但是,如果你的“后台”程序多于5个,那么先进入坟墓里面躺着的那个就不好意思了。要把你挖出来扔掉,让新来的进去躺着。这样的话,你想借尸还魂连尸体都找不到了。而且尸体消失的那一刻,内存中的魂也烟消云散了。
这个机制涉及到的是应用程序的生命周期问题。这个问题网上一搜一大堆。就没啥好讨论的。简单来说,一开始程序运行,启动的是Launch。然后如果点击开始键,那么程序就进入Deactivate,程序进入“后台”,如果再次点击返回键,程序就能从“后台”恢复。就是Activate。再次多次点击返回键返回到桌面。程序就退出了。就是Closing。这些东西在App.xaml都有定义。
还有一个关键的是,从“后台”返回程序只能按返回键,如果是从启动器上启动程序,那么前面的程序的线程就退出了。就是你重新打开了一个新的程序,这点我很不爽。如果我的程序是在第五个,那么只有2种方法从“后台”启动程序,一种是长按返回键,然后自己选择进入后台程序,另一种是一种狂按返回键,把前面四个“后台”程序退出了就返回到第五个程序了。
所以,让我很不爽的就是这两点,一是只有5个“后台程序”,二是不能从启动器进入后台。
那么,只有自己模拟实现了。在Deactivate的时候,把数据都存在IsolatedStorage里面。
下面实现的是拥有两个页面的程序,模拟在第二个页面进入“后台”,所以仅仅恢复第二个页面的数据。
首先添加一个叫Page2.xaml的页面。并且在上面放上一个TextBox,Name为Page2Msg,
然后在MainPage.xaml放上一个Button,用来导航到Page2.xaml,添加click事件:
private void Button_Click(object sender, RoutedEventArgs e)
{
NavigationService.Navigate(new Uri("/TombStoneDemo;component/Page2.xaml",UriKind.Relative));
}
接下来就是重点了。我把当前所在页面保存到PhoneApplicationService。并且把Page2上的TextBox的内容也保存到PhoneApplicationService。定义了一个IsolatedStorageSettings,key为“Recovery",布尔值,用来保存是否要恢复中断数据。
具体实现如下:
在MainPage的Loaded事件中实现:
private void PhoneApplicationPage_Loaded(object sender, RoutedEventArgs e)
{
IsolatedStorageSettings iss = IsolatedStorageSettings.ApplicationSettings;
bool recov;
if (iss.TryGetValue("Recovery", out recov))
{
if (recov)//是否恢复,恢复就导向Page2
{
if (PhoneApplicationService.Current.State.ContainsKey("CurrentPage"))
{
string temp = Convert.ToString(PhoneApplicationService.Current.State["CurrentPage"]);
if (!temp.Equals("MainPage.xaml") && temp.Length > 0)
{
NavigationService.Navigate(new Uri("/TombStoneDemo;component/" + temp, UriKind.Relative));//导航到CurrentPage。也就是以前的中断页面
}
}
}
else
PhoneApplicationService.Current.State["CurrentPage"] = "MainPage.xaml";
}
else
PhoneApplicationService.Current.State["CurrentPage"] = "MainPage.xaml";
}
在Page2中添加代码:
private void PhoneApplicationPage_Loaded(object sender, RoutedEventArgs e)
{
Debug.WriteLine("Page2 Loaded");
IsolatedStorageSettings iss = IsolatedStorageSettings.ApplicationSettings;
bool recov;
if (iss.TryGetValue("Recovery", out recov))
{
if (recov)
{
if (PhoneApplicationService.Current.State.ContainsKey("CurrentPage"))
{
string temp = Convert.ToString(PhoneApplicationService.Current.State["CurrentPage"]);
if (temp.Equals("Page2.xaml"))
{
if (PhoneApplicationService.Current.State.ContainsKey("Page2txMsg"))
{
txMsg.Text = (string)PhoneApplicationService.Current.State["Page2txMsg"];
iss["Recovery"] = false;//恢复后设置这个属性为false,就是恢复了
}
}
}
}
}
PhoneApplicationService.Current.State["CurrentPage"] = "Page2.xaml";
}
protected override void OnNavigatedFrom(System.Windows.Navigation.NavigationEventArgs e)
{
base.OnNavigatedFrom(e);
//离开Page2的时候保存TextBox的值
PhoneApplicationService.Current.State["Page2txMsg"] = txMsg.Text;
}
了解TombStone的都知道,这个 PhoneApplicationService只是保存在内存中,如果从启动器启动程序,原来的内存里面的内容也会被销毁。所以,我要在中断程序的时候把这些数据都保存到IsolatedStorage。
在App.xaml里面的Launching,Deactivate,CLosing添加代码:
IsolatedStorageSettings iss = IsolatedStorageSettings.ApplicationSettings;
private void Application_Launching(object sender, LaunchingEventArgs e)
{ //程序启动的时候从存储里面读取数据
string temp;
if (iss.TryGetValue("LastPage", out temp))
{
PhoneApplicationService.Current.State["CurrentPage"] = temp;
}
if (iss.TryGetValue("Page2txMsg", out temp))
{
PhoneApplicationService.Current.State["Page2txMsg"] = temp;
}
}
private void Application_Deactivated(object sender, DeactivatedEventArgs e)
{//程序中断的时候保存数据到IsolatedStorage。
iss["LastPage"] = PhoneApplicationService.Current.State["CurrentPage"];
iss["Recovery"] = true;
iss["Page2txMsg"] = PhoneApplicationService.Current.State["Page2txMsg"];
}
private void Application_Closing(object sender, ClosingEventArgs e)
{
iss["Recovery"] = false;
}
这样,就可以了。现在在Page2输入任何数据到TextBox里面。然后点击开始键。现在无论从返回键进入程序,还是从启动器启动程序,都会返回到我们刚才未编辑完的Page2界面。这样,就模拟了多任务运行。
总结:现在是可以模拟了多任务运行。问题就是如果控件太多。页面太多,那么写起来相当繁琐。