慎用匿名委托 Dispatcher.BeginInvoke导致UI卡死之发现

先描述一下需求,服务器程序需要对终端的在线状态进行跟踪,采用ping的发放获取信息,在ping通或者ping不通后需要对UI进行更新,下面是出问题的代码(此例ping的方法比较简单,尚未进行应用测试勿用作实际用途):

 

 1     public partial class MainWindow : Window
 2     {
 3         public MainWindow()
 4         {
 5             InitializeComponent();
 6         }
 7         List<string> ClientInfoList = new List<string>();
 8         private void Window_Loaded(object sender, RoutedEventArgs e)
 9         {
10             for (int i = 1; i < 50; i++)
11             {
12                 ClientInfoList.Add("192.168.1." + i.ToString());
13             }
14 
15             ThreadPool.QueueUserWorkItem(
16                delegate
17                {
18                    while (true)
19                    {
20                        Debug.WriteLine(DateTime.Now.ToString() + "Ping");
21                        int OnLineCout = 0;
22                        Ping pingSender = new Ping();
23                        PingOptions options = new PingOptions();
24                        for (int i = 0; i < ClientInfoList.Count; i++)
25                        {
26                            if (ClientInfoList[i] != "")
27                            {
28                                options.DontFragment = true;
29                                bool PingSuceess = false;
30                                PingReply reply = pingSender.Send(ClientInfoList[i], 100);
31                                if (reply.Status == IPStatus.Success)
32                                {
33                                    PingSuceess = true;
34                                }
35                        
36                                if (!PingSuceess)
37                                {
38                                    Debug.WriteLine(DateTime.Now.ToString() + "Ping失败,终端IP:" + ClientInfoList[i]);
39                                    this.Dispatcher.BeginInvoke((Action)delegate()
40                                     {
41                                         label1.Content = ClientInfoList[i];
42                                     });
43                                }
44                                else
45                                {
46                                    OnLineCout++;
47                                }
48 
49                            }
50                        }
51                        Debug.WriteLine(DateTime.Now.ToString() + "PingOver");
52                        Thread.Sleep(3000);
53                    }
54                }, null);
55 
56         }
57 
58         private void button1_Click(object sender, RoutedEventArgs e)
59         {
60             button1.Content = new Random().Next();
61         }
62     }

第39行为更新UI的方法,当循环执行完毕后执行第二次循环后,会不定期出现程序异常。实际的应用比这个例子代码要复杂很多,所以不断的注释,使代码简化,最终将问题锁定在本例中的39行附近,后来一直是怀疑不该使用this.Dispatcher.BeginInvoke这种方式来实现。再后来采用DispatcherTimer类来实现,由于程序其它线程也要操作一些UI对象,使用这种方式又导致UI响应太慢,出现卡顿现象(再多的DispatcherTimer都使用一个线程来调度,所以DispatcherTimer开的越多,UI越卡)。再后来找到了老赵的帖子《

警惕匿名方法造成的变量共享》受到启发,开始怀疑是匿名实现this.Dispatcher.BeginInvoke 造成的,后将代码改为以下:

 

 1     public partial class MainWindow : Window
 2     {
 3         public MainWindow()
 4         {
 5             InitializeComponent();
 6         }
 7         List<string> ClientInfoList = new List<string>();
 8         delegate void UpdateUI(string str);
 9 
10         void UpdateUIMethod(string str)
11         {
12             label1.Content = str;
13         }
14         private void Window_Loaded(object sender, RoutedEventArgs e)
15         {
16             for (int i = 1; i < 50; i++)
17             {
18                 ClientInfoList.Add("192.168.1." + i.ToString());
19             }
20             UpdateUI UUI = new UpdateUI(UpdateUIMethod);
21             ThreadPool.QueueUserWorkItem(
22                delegate
23                {
24                    while (true)
25                    {
26                        Debug.WriteLine(DateTime.Now.ToString() + "Ping");
27                        int OnLineCout = 0;
28                        Ping pingSender = new Ping();
29                        PingOptions options = new PingOptions();
30                        for (int i = 0; i < ClientInfoList.Count; i++)
31                        {
32                            if (ClientInfoList[i] != "")
33                            {
34                                options.DontFragment = true;
35                                bool PingSuceess = false;
36                                PingReply reply = pingSender.Send(ClientInfoList[i], 100);
37                                if (reply.Status == IPStatus.Success)
38                                {
39                                    PingSuceess = true;
40                                }
41 
42                                if (!PingSuceess)
43                                {
44                                    Debug.WriteLine(DateTime.Now.ToString() + "Ping失败,终端IP:" + ClientInfoList[i]);
45                                    //this.Dispatcher.BeginInvoke((Action)delegate()
46                                    // {
47                                    //     label1.Content = ClientInfoList[i];
48                                    // });
49                                    this.Dispatcher.BeginInvoke(UUI, ClientInfoList[i]);
50                                }
51                                else
52                                {
53                                    OnLineCout++;
54                                }
55 
56                            }
57                        }
58                        Debug.WriteLine(DateTime.Now.ToString() + "PingOver");
59                        Thread.Sleep(3000);
60                    }
61                }, null);
62 
63         }
64 
65         private void button1_Click(object sender, RoutedEventArgs e)
66         {
67             button1.Content = new Random().Next();
68         }
69     }

 

 

posted on 2011-11-25 14:42 badnewfish 阅读(145) 评论(0) 编辑 收藏

导航

<2011年11月>
303112345
6789101112
13141516171819
20212223242526
27282930123
45678910

公告


点击这里给我发消息 
北京礼品网

巴顿的博客

昵称:badnewfish
园龄:5年3个月
粉丝:2
关注:0

搜索

 

常用链接

我的标签

随笔分类

随笔档案

相册

最新评论

阅读排行榜

评论排行榜

推荐排行榜