Silverlight+WCF 实战-网络象棋最终篇之非线程阻塞倒计时窗口(四)
前言:
在前面的系列中,我們雖然完成了其大部分功能,但是,離正真運(yùn)行,還是有一大段距離當(dāng)你F5運(yùn)行時(shí),在彈出對(duì)話框之后,如果你不即時(shí)點(diǎn)確定,或者上個(gè)WC回來(lái)之后,你會(huì)發(fā)現(xiàn)已經(jīng)提示出錯(cuò)了
這節(jié)開(kāi)始,我們將對(duì)其進(jìn)行一小步一小步的優(yōu)化,來(lái)避免一些明顯容易引發(fā)的錯(cuò)誤。
?
感知一下最原始的消息彈出框如下圖:
?
?
一:傳統(tǒng)消息框,容易引發(fā)命案
?
1:原始的消息框,是線程阻塞類型的,很容易引發(fā)超時(shí)問(wèn)題
線程阻塞?怎么理解?
簡(jiǎn)單的說(shuō)就是,WCF服務(wù)端給客戶端發(fā)送了消息提示之后,一直進(jìn)入等待狀態(tài),直到玩家點(diǎn)了確定,這時(shí)才繼續(xù)做其它事情。?
會(huì)產(chǎn)生什么問(wèn)題?
玩家上WC去了?消息沒(méi)人確認(rèn),自然就會(huì)超時(shí)引發(fā)異常了,而且那線程也沒(méi)法接下去干其它活。?
解決方案?
a:傳統(tǒng)解決方案[加上倒計(jì)時(shí),還是線程阻塞類型]
?
當(dāng)初我只是想在這傳統(tǒng)的消息框上加上倒計(jì)時(shí)自動(dòng)確認(rèn),這樣可以少一點(diǎn)避免超時(shí)情況。于是搜了一些資料,發(fā)現(xiàn)要用winapi來(lái)處理,這個(gè)這個(gè)....大才小用了吧。
?
b:更優(yōu)的解決方案
無(wú)意中發(fā)現(xiàn)Silverlight的ChildWindow,正好解決了這一問(wèn)題。因?yàn)?ChildWindow使用異步方式,非線程阻塞,消息一彈之后線程就回家去了。
而且用Sivlerlight內(nèi)置的定時(shí)器DispatcherTimer,非常容易實(shí)現(xiàn)倒計(jì)時(shí)。
?
二:實(shí)現(xiàn)自定義非線程阻塞倒計(jì)時(shí)對(duì)話框,純種Sivlerlight
?
1:看看純種的長(zhǎng)成什么樣
新建項(xiàng)目-》Silverlight?子窗口?-》起名叫MsgBox-》找另一個(gè)界面調(diào)用一下。比如在登陸頁(yè)面測(cè)試一下:MsgBox?box=new?MsgBox();box.Show();
?
結(jié)果所見(jiàn)如圖:
說(shuō)明:
1:有背景灰色層,界面原生的還傳統(tǒng)消息框好看多了。2:重點(diǎn)提示:當(dāng)初剛試的時(shí)候是直接運(yùn)行MsgBox,然后在其構(gòu)造函數(shù)中調(diào)用Show(),結(jié)果是出不來(lái)的。
?
2:改造-界面小小改動(dòng)
我們將原來(lái)的xaml改造成如下:
<controls:ChildWindow?x:Class="ChessProject.MsgBox"?...省略一點(diǎn)...??Width="290"?Height="141"??Title="系統(tǒng)消息">????<Grid?x:Name="LayoutRoot"?Margin="2"?Height="97"?Width="270">
????????<Button?Visibility="Collapsed"?x:Name="CancelButton"?Content="取消"?Click="CancelButton_Click"?Width="75"?Height="23"?HorizontalAlignment="Right"?Margin="0,62,93,12"?/>
????????<Button?x:Name="OKButton"?Content="確定"?Click="OKButton_Click"?Width="75"?Height="23"?HorizontalAlignment="Right"?Margin="0,62,10,12"?/>
????????<TextBlock?Height="41"?TextWrapping="Wrap"?HorizontalAlignment="Left"?Margin="15,15,0,0"?Name="tbMsg"?Text="請(qǐng)按確定按鈕確定"?VerticalAlignment="Top"?Width="224"?/>
????</Grid>
</controls:ChildWindow>
?
界面效果如圖,和上圖差不多[這里把取消放在前面,只是為了不顯示取消時(shí),確定還保留在原位好看點(diǎn)]:
?
3:改造,在標(biāo)題加入倒計(jì)時(shí)
a:加入計(jì)時(shí)器并初始化
???????DispatcherTimer?timer;//定時(shí)器????????public?MsgBox()
????????{
????????????InitializeComponent();
????????????timer?=?new?DispatcherTimer();
????????????timer.Interval?=?TimeSpan.FromSeconds(1);
????????????timer.Tick?+=?new?EventHandler(timer_Tick);
????????}
b:新加show方法并實(shí)現(xiàn)倒計(jì)時(shí)
???????int?defaultTime?=?3;//默認(rèn)N秒????????string?userTitle;
???????DispatcherTimer?timer;//定時(shí)器
????????public?MsgBox()
????????{
????????????//...省略...
????????}
????????void?timer_Tick(object?sender,?EventArgs?e)
????????{
????????????Title?=?string.Format(userTitle?+?"?[倒計(jì)時(shí)自動(dòng)確定:{0}秒]",?defaultTime);
????????????defaultTime--;
????????????if?(defaultTime?==?0)
????????????{
????????????????ResetTimer();
????????????}
????????}
????????void?ResetTimer()
????????{
????????????timer.Stop();
????????????defaultTime?=?3;
????????}
????????public?void?Show(string?msg,?string?title)
????????{
????????????tbMsg.Text?=?msg;
????????????userTitle?=?title;
????????????Show();
????????????timer.Start();
????????}
c:再調(diào)用一下看結(jié)果
MsgBox?box?=?new?MsgBox();box.Show("http://cyq1162.cnblogs.com","路過(guò)秋天");
如圖:
?
4:擴(kuò)展show函數(shù):加入回調(diào)/倒計(jì)時(shí)時(shí)間/按鈕類型/默認(rèn)確認(rèn)類型
首先:這個(gè)子窗口是異步的,所以,在點(diǎn)擊完確定時(shí),需要增加多一個(gè)回調(diào)函數(shù);接著:默認(rèn)3秒,很明顯情況不同,時(shí)間也要稍為增加變動(dòng)一下;
然后:有時(shí)候按鈕只是確定,有時(shí)候就是取消+確定; 最后:倒計(jì)時(shí)時(shí)間到了,默認(rèn)執(zhí)行確定,還是執(zhí)行取消。
?
于是,要實(shí)現(xiàn)了:
a:如何實(shí)現(xiàn)回調(diào)?
默認(rèn)子窗口就有Closed事件,我們用它的事件,在點(diǎn)擊確定或取消時(shí),執(zhí)行Close()方法
????????public?MsgBox()????????{
????????????InitializeComponent();
????????????timer?=?new?DispatcherTimer();
????????????timer.Interval?=?TimeSpan.FromSeconds(1);
????????????timer.Tick?+=?new?EventHandler(timer_Tick);
????????????this.Closed?+=?new?EventHandler(MsgBox_Closed);
????????}
????????void?MsgBox_Closed(object?sender,?EventArgs?e)
????????{
????????????//待實(shí)現(xiàn)
?????????}
????????private?void?OKButton_Click(object?sender,?RoutedEventArgs?e)
????????{
????????????this.DialogResult?=?true;
????????????Close();//調(diào)用一下關(guān)閉
????????}
????????private?void?CancelButton_Click(object?sender,?RoutedEventArgs?e)
????????{
????????????this.DialogResult?=?false;
????????????Close();//調(diào)用一下關(guān)閉
????????}
?
問(wèn)題?我們難道對(duì)所有的確定都執(zhí)行相同的代碼?
首先說(shuō):異步不能像同步那樣寫if(show(xxx,xxx)){方法}于是說(shuō):這是個(gè)很嚴(yán)重的問(wèn)題,因?yàn)椴煌拇_定,我們執(zhí)行的事件肯定是不同的。
?
解決問(wèn)題?匿名委托出手了!!!
匿名委托:[Action<T1,T2,T3...N個(gè)重載>],這是個(gè)很好用的東東,可以傳進(jìn)方法名稱,在執(zhí)行后調(diào)用不同的方法。?
匿名委托實(shí)現(xiàn):
Action<bool>?callBackEvent;//全局定義void?MsgBox_Closed(object?sender,?EventArgs?e)
{
????if?(callBackEvent?!=?null)
????{
????????callBackEvent(DialogResult.Value);
????}
}
?
那委托是如何傳入的?Show方法增加擴(kuò)展參數(shù)傳入。
b:這里貼出完整代碼,一并實(shí)現(xiàn):倒計(jì)時(shí)時(shí)間/按鈕類型/默認(rèn)確認(rèn)類型
完整的MsgBox代碼 ????public?partial?class?MsgBox?:?ChildWindow????{
????????int?defaultTime?=?3;//默認(rèn)N秒
????????string?userTitle;
????????DispatcherTimer?timer;//定時(shí)器
????????Action<bool>?callBackEvent;
????????bool?autoOKConfirm?=?true;
????????public?MsgBox()
????????{
????????????InitializeComponent();
????????????timer?=?new?DispatcherTimer();
????????????timer.Interval?=?TimeSpan.FromSeconds(1);
????????????timer.Tick?+=?new?EventHandler(timer_Tick);
????????????this.Closed?+=?new?EventHandler(MsgBox_Closed);
????????}
????????void?MsgBox_Closed(object?sender,?EventArgs?e)
????????{
????????????//待實(shí)現(xiàn)
????????}
????????void?timer_Tick(object?sender,?EventArgs?e)
????????{
????????????Title?=?string.Format(userTitle?+?"?[倒計(jì)時(shí)自動(dòng)確定:{0}秒]",?defaultTime);
????????????defaultTime--;
????????????if?(defaultTime?==?0)
????????????{
????????????????ResetTimer();
????????????????if?(autoOKConfirm)
????????????????{
????????????????????OKButton_Click(null,?null);
????????????????}
????????????????else
????????????????{
????????????????????CancelButton_Click(null,?null);
????????????????}
????????????}
????????}
????????void?ResetTimer()
????????{
????????????timer.Stop();
????????????defaultTime?=?3;
????????}
????????public?void?Show(string?msg,?string?title)
????????{
????????????Show(msg,?title,?defaultTime,?null,?true,?MessageBoxButton.OK);
????????}
????????public?void?Show(string?msg,?string?title,?int?timeSecond,?Action<bool>?callBack)
????????{
????????????Show(msg,?title,?timeSecond,?callBack,?false,?MessageBoxButton.OKCancel);
????????}
????????public?void?Show(string?msg,?string?title,?int?timeSecond,?Action<bool>?callBack,?bool?autoOK,?MessageBoxButton?button)
????????{
????????????tbMsg.Text?=?msg;
????????????userTitle?=?title;
????????????if?(button?==?MessageBoxButton.OK)
????????????{
????????????????OKButton.Content?=?"確定";
????????????????CancelButton.Visibility?=?System.Windows.Visibility.Collapsed;
????????????}
????????????else
????????????{
????????????????CancelButton.Visibility?=?System.Windows.Visibility.Visible;
????????????????OKButton.Content?=?"同意";
????????????????CancelButton.Content?=?"拒絕";
????????????}
????????????defaultTime?=?timeSecond;
????????????autoOKConfirm?=?autoOK;
????????????callBackEvent?=?callBack;
????????????Show();
????????????timer.Start();
????????}
????????private?void?OKButton_Click(object?sender,?RoutedEventArgs?e)
????????{
????????????this.DialogResult?=?true;
????????}
????????private?void?CancelButton_Click(object?sender,?RoutedEventArgs?e)
????????{
????????????this.DialogResult?=?false;
????????}
????}
?
?
三:接下來(lái)便是苦力活了,把原來(lái)用到傳統(tǒng)對(duì)框的提示,通通改過(guò)來(lái)。
這個(gè)改的點(diǎn)有點(diǎn)多,留到下節(jié)MsgBox使用時(shí)細(xì)細(xì)說(shuō)了。?
最后上一實(shí)際應(yīng)用中的圖:
轉(zhuǎn)載于:https://www.cnblogs.com/cyq1162/archive/2010/10/27/1861281.html
總結(jié)
以上是生活随笔為你收集整理的Silverlight+WCF 实战-网络象棋最终篇之非线程阻塞倒计时窗口(四)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 关于进程和线程以及句柄
- 下一篇: XV6850成功刷机步骤