前言:
最近有網友經常會問,在跟着做象棋對戰的通訊中,在重複退出進入的時候,消息會重複出現,本節就這問題進行解說與優化。
一:分析問題產生的原因?
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裏,構造函數的初始化:
public
Login()
{
InitializeComponent();
App.client.LoginCompleted
+=
new
EventHandler
<
System.ComponentModel.AsyncCompletedEventArgs
>
(client_LoginCompleted);
Load();
}
我們對App.client.LoginCompleted初始化了一次事件,這時一切是正常的,接着我們進入房間,之後,我們返回系統回到登陸。
3:接着看退出系統的按鈕是怎麼返回到登陸頁面的:
//
退出系統
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 控件()的方式在各個頁面切換時,於是容易產生這種問題。
二:解決消息重複問題
從第一步中,我們分析到問題產生的根源,於是,我們可以想出很多方式,來解決這種問題,這裏我介紹兩種方式:
先來看一下錯誤任法:註冊事件前加先減,再加,示例代碼如下:
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全局定義每個房間的變量,並改造成屬性,所幸控件就幾個,定義也費不了多少力,代碼如下:
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