天天看點

WP7的Tombstone機制(墓碑機制)。多任務開發研究

     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界面。這樣,就模拟了多任務運作。

總結:現在是可以模拟了多任務運作。問題就是如果控件太多。頁面太多,那麼寫起來相當繁瑣。

繼續閱讀