Silverlight+WCF 實戰-網絡象棋最終篇之解決重複的消息提示(八)

前言:

最近有網友經常會問,在跟着做象棋對戰的通訊中,在重複退出進入的時候,消息會重複出現,本節就這問題進行解說與優化。

 

一:分析問題產生的原因?

 

1:首先看App.xaml,裏面定義了一個全局客戶端回調:

public   static  GameService.ServiceClient client; // 回調的客戶端

 

並且這個回調我們全局只實例化一次,並且默認加載時定位到登陸頁面:

private   void  Application_Startup( object  sender, StartupEventArgs e)
{
   
this .RootVisual  =  root;
   root.Children.Add(
new  Login()); // 默認定位到登錄頁面。
}

 

2:再看登錄頁面Login.xaml裏,構造函數的初始化:

複製代碼
ExpandedBlockStart.gif
public  Login()
{
            InitializeComponent();
            App.client.LoginCompleted 
+=   new  EventHandler < System.ComponentModel.AsyncCompletedEventArgs > (client_LoginCompleted);
            Load();
}
複製代碼

我們對App.client.LoginCompleted初始化了一次事件,這時一切是正常的,接着我們進入房間,之後,我們返回系統回到登陸。

 

3:接着看退出系統的按鈕是怎麼返回到登陸頁面的:

複製代碼
ExpandedBlockStart.gif
         // 退出系統
         private   void  btnLogout_Click( object  sender, RoutedEventArgs e)
        {
            
if  (App.chess.IsGaming)
            {
                btnGameLose_Click(
null null ); // 發送認輸
                App.chess.IsGaming  =   false ;
            }
            App.client.OutRoomAsync(App.player, App.player.RoomID, App.player.AttachInfo);
            ((App)Application.Current).RedirectTo(
new  Login());
        }
複製代碼

看最後一行,我們又New Login了,這種情況,剛纔第二步中的:App.client.LoginCompleted事件將被重複註冊,因此,重複的事件註冊引發了重複的消息提示。

 

問題總結說明:

對於消息的重複提示,基本都屬於事件的重複註冊造成的,我們之前的代碼很多轉向都使用new 控件()的方式在各個頁面切換時,於是容易產生這種問題。

 

 

二:解決消息重複問題

 

從第一步中,我們分析到問題產生的根源,於是,我們可以想出很多方式,來解決這種問題,這裏我介紹兩種方式:

 

先來看一下錯誤任法:註冊事件前加先減,再加,示例代碼如下:

ExpandedBlockStart.gif
App.client.LoginCompleted  -=   new  EventHandler < System.ComponentModel.AsyncCompletedEventArgs > (client_LoginCompleted);
App.client.LoginCompleted 
+=   new  EventHandler < System.ComponentModel.AsyncCompletedEventArgs > (client_LoginCompleted);

網上有人說:每次註冊前先去掉一下,然後再增加,邏輯上看起來好像沒問題,剛自己試了下,純忽悠型。

 

現在介紹下我想到的兩種方式:

1:定義全局變量List<事件名稱>,保存註冊過的事件名稱

邏輯:在每次事件產生前,先判斷一下事件是否存在,不存在則添加,存在則跳過,此方法實現簡單,大夥一說就應該會了,所以直接跳過了。

 

2:定義全局變量保存所有房間,於是在RedirectTo切換房間的時候,避免使用New 控件() 來避免再次執行事件註冊事件

下面進行代碼整改:

A:App.xaml全局定義每個房間的變量,並改造成屬性,所幸控件就幾個,定義也費不了多少力,代碼如下:

複製代碼
ExpandedBlockStart.gif
         private   static  Login loginObj;
        
public   static  Login LoginObj
        {
            
get
            {
                
if  (loginObj  ==   null )
                {
                    loginObj 
=   new  Login();
                }
                
// loginObj.Reset();
                 return  loginObj;
            }
        }
        
private   static  Room roomObj;
        
public   static  Room RoomObj
        {
            
get
            {
                
if  (roomObj  ==   null )
                {
                    roomObj 
=   new  Room();
                }
                
// roomObj.Reset();
                 return  roomObj;
            }
        }
        
private   static  Index indexObj;
        
public   static  Index IndexObj
        {
            
get
            {
                
if  (indexObj  ==   null )
                {
                    indexObj 
=   new  Index();
                }
                
// indexObj.Reset();
                 return  indexObj;
            }
        }
複製代碼

 

說明:

這裏有兩點:1是改造屬性方式,這樣在調用時不用再寫判斷語句,2是註冊的Reset()方法,後面會開啓到。

 

B:查找調用RedirectTo切換界面的代碼,替換爲:App.xxxxObj

 

隨便找個RedirectTo,右鍵查找所有引用,看看有幾個要修改的地方,所幸也不多,如下圖:

 

說明:

按上面的查找出來的代碼,一個一個更改即可,如把new Index()換成App.IndexObj。

 

 

OK,消息提示重複的問題,至此,是解決了,但是,將產生一點副作用,就是切回去的時候,狀態需要重置。

 

簡單的示例說明就是:

點登陸時,把按鈕設置爲不可用,然後你進去,再退出,看到的是「不可用」的按鈕就沒法再進去了。

 

OK,狀態重置的問題,就留到下節解決了。

 

本節沒關聯啥好看圖片,就隨便掛一張在下面讓大夥欣賞了:

 

最後:謝謝大家對本系列的喜歡,謝謝支持~

同時歡迎大家多到 秋色園 走走~~~

PS:傳說點一下推薦會有10個園豆的規則已經取消了,不過,喜歡的還是可以點一下「推薦」,thank you very much!!

版權聲明:本文原創發表於博客園,作者爲路過秋天,原文鏈接:

http://www.cnblogs.com/cyq1162/archive/2011/01/05/1926344.html