• <code id="58gs9"></code>

      <mark id="58gs9"></mark>
      1. 当前位置£º首页 > 开发教程 > WCF技术 >

        Silverlight+WCF 实战-网络象棋最终篇之非线程阻塞倒计时窗口(四

        时间£º2014-05-20 16:40 来源£º 作者£º 浏览£º收藏 挑错 推荐 打印

        前言£º

        在前面的系列中£¬我们虽然完成了其大部分功能£¬但是£¬离正真运行£¬还是有一大段距离

        当你F5运行时£¬在弹出对话框之后£¬如果你不即时点确定£¬或者上个WC回来之后£¬你会发现已经提示出错了

        这节开始£¬我们将对其进行一小步一小步的优化£¬来避免一些明显容易引发的错误¡£

         

        感知一下最原始的消息弹出框如下图£º

         

        Silverlight+WCF 实战-网络象棋最终篇之非线程阻塞倒计时窗口(四

         

        一£º传统消息框£¬容易引发命案

         

        1£º原始的消息框£¬是线程阻塞类型?#27169;?#24456;容易引发超时问题

        线程阻塞£¿怎么理解£¿

        简单的说就是£¬WCF服务端给客户端发送了消息提示之后£¬一直进入等待状态£¬直到玩家点了确定£¬这时才继续做其它事情¡£

         

        会产生什?#27425;?#39064;£¿

        玩家上WC去了£¿消息没人确认£¬自然就会超时引发异常了£¬而且那线程也没法接下去干其它活¡£

         

        解决方案£¿

        a£º传统解决方案[加上倒计时£¬还是线程阻塞类型]

         

        当初我只是想在这传统的消息框上加上倒计时自动确认£¬这样可以少一点避免超时情况¡£
        于是搜了一些资料£¬发现要用winapi来处理£¬这个这个....大才小用了吧¡£

         

        b£º更优的解决方案

        无意中发现Silverlight的ChildWindow£¬正好解决了这一问题¡£
        因为 ChildWindow使用异步方式£¬非线程阻塞£¬消息一弹之后线程就回家去了¡£
        而且用Sivlerlight内置的定时器DispatcherTimer£¬非常容易实现倒计时¡£

         

        二£º实现自定义非线程阻塞倒计时对话框£¬纯种Sivlerlight

         

        1£º?#32431;?#32431;?#20540;?#38271;成什么样

        新建项目-¡·Silverlight 子窗口 -¡·起名叫MsgBox-¡·找另一个界面调用一下¡£
        ?#28909;?#22312;登陆页面测试一下£ºMsgBox box=new MsgBox();box.Show();

         

        结果所见如图£º

        Silverlight+WCF 实战-网络象棋最终篇之非线程阻塞倒计时窗口(四

        ?#24471;ö?/p>

        1£º有背景灰色层£¬界面原生的还传统消息框好看多了¡£
        2£º重点提示£º当初刚试的时候是直接运行MsgBox£¬然后在其构造函数中调用Show()£¬结果是出不来的¡£

         

        2£º改造-界面小小改动

        我们将原来的xaml改造成如下£º

        Silverlight+WCF 实战-网络象棋最终篇之非线程阻塞倒计时窗口(四
        <controls:ChildWindow x:Class="ChessProject.MsgBox" ...省略一点...  Width="290" Height="141"  Title="系统消息">
            
        <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="请按确定按钮确定" VerticalAlignment="Top" Width="224" />
            
        </Grid>
        </controls:ChildWindow>

         

        界面效果如图£¬和上图差不多[这里把取消放在前面£¬只是为了不显示取消时£¬确定还保留在原位好看点]:

        Silverlight+WCF 实战-网络象棋最终篇之非线程阻塞倒计时窗口(四

         

        3£º改造£¬在标题加入倒计时

        a£º加入计时器并初始化

        Silverlight+WCF 实战-网络象棋最终篇之非线程阻塞倒计时窗口(四
               DispatcherTimer timer;//定时器
                public MsgBox()
                {
                    InitializeComponent();
                    timer 
        = new DispatcherTimer();
                    timer.Interval 
        = TimeSpan.FromSeconds(1);
                    timer.Tick 
        += new EventHandler(timer_Tick);
                }

        b£º新加show方法并实现倒计时

        Silverlight+WCF 实战-网络象棋最终篇之非线程阻塞倒计时窗口(四
               int defaultTime = 3;//默认N秒
                string userTitle;
               DispatcherTimer timer;
        //定时器
                public MsgBox()
                {
                    
        //...省略...
                }
                
        void timer_Tick(object sender, EventArgs e)
                {
                    Title 
        = string.Format(userTitle + " [倒计时自动确定:{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£º再调用一下看结果

        MsgBox box = new MsgBox();
        box.Show(
        "http://cyq1162.cnblogs.com","路过秋天");

        如图£º

        Silverlight+WCF 实战-网络象棋最终篇之非线程阻塞倒计时窗口(四

         

        4£º扩展show函数£º加入回调/倒计时时间/按钮类型/默认确认类型

        首先£º这个子窗口是异步?#27169;?#25152;以£¬在点击完确定时£¬需要增加多一个回调函数£»
        接着£º默认3秒£¬很明显情况不同£¬时间也要稍为增加变动一下£»
        然后£º有时候按钮只是确定£¬有时候就是取消+确定£»
        最后£º倒计时时间到了£¬默?#29616;?#34892;确定£¬还是执行取消¡£

         

        于是£¬要实现了£º

        a£º如何实现回调£¿

        默认子窗口就有Closed事件£¬我们用它的事件£¬在点击确定或取消时£¬执行Close()方法

        Silverlight+WCF 实战-网络象棋最终篇之非线程阻塞倒计时窗口(四
                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)
                {
                    
        //待实现
                 }
                
        private void OKButton_Click(object sender, RoutedEventArgs e)
                {
                    
        this.DialogResult = true;
                    Close();
        //调用一下关闭
                }

                
        private void CancelButton_Click(object sender, RoutedEventArgs e)
                {
                    
        this.DialogResult = false;
                    Close();
        //调用一下关闭
                }

         

        问题£¿我们难道?#36816;?#26377;的确定都执行相同的代码£¿

        首先说£º异步不能像同步那样写if(show(xxx,xxx)){方法}
        于是说£º这是个很?#29616;?#30340;问题£¬因为不同的确定£¬我们执行的事件肯定是不同的¡£

         

        解决问题£¿匿名委托出手了£¡£¡£¡

        匿名委托£º[Action<T1,T2,T3...N个重载>]£¬这是个很好用的东东£¬可?#28304;?#36827;方法名称£¬在执行后调用不同的方法¡£

         

        匿名委托实现£º

        Action<bool> callBackEvent;//全局定义

        void MsgBox_Closed(object sender, EventArgs e)
        {
            
        if (callBackEvent != null)
            {
                callBackEvent(DialogResult.Value);
            }
        }

         

        那委托是如何传入?#27169;¿Show方法增加扩展参数传入¡£

        b£º这里贴出完整代码£¬一并实现£º倒计时时间/按钮类型/默认确认类型

        Silverlight+WCF 实战-网络象棋最终篇之非线程阻塞倒计时窗口(四完整的MsgBox代码
            public partial class MsgBox : ChildWindow
            {
                
        int defaultTime = 3;//默认N秒
                string userTitle;
                DispatcherTimer timer;
        //定时器
                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)
                {
                    
        //待实现
                }
                
        void timer_Tick(object sender, EventArgs e)
                {
                    Title 
        = string.Format(userTitle + " [倒计时自动确定:{0}秒]", defaultTime);
                    defaultTime
        --;
                    
        if (defaultTime == 0)
                    {
                        ResetTimer();
                        
        if (autoOKConfirm)
                        {
                            OKButton_Click(
        nullnull);
                        }
                        
        else
                        {
                            CancelButton_Click(
        nullnull);
                        }
                    }
                }
                
        void ResetTimer()
                {
                    timer.Stop();
                    defaultTime 
        = 3;
                }
                
        public void Show(string msg, string title)
                {
                    Show(msg, title, defaultTime, 
        nulltrue, 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;
                }
            }

         

         

        三£º接下来便是苦力活了£¬?#35328;?#26469;用到传统对框的提示£¬通通改过来¡£

        这个改的点有点多£¬留到下节MsgBox使用时细细说了¡£

         

        最后上一实?#35270;?#29992;中的图£º

        Silverlight+WCF 实战-网络象棋最终篇之非线程阻塞倒计时窗口(四

        Silverlight+WCF 实战-网络象棋最终篇之非线程阻塞倒计时窗口(四转载<\/script>' );
        ´ó¸»ÎÌÆåÅÆÓéÀÖ¹ÙÍø

      2. <code id="58gs9"></code>

          <mark id="58gs9"></mark>

          1. <code id="58gs9"></code>

              <mark id="58gs9"></mark>