>

享用一下防止外人继续踩,近日用Timer踩了三个坑

- 编辑:www.bifa688.com -

享用一下防止外人继续踩,近日用Timer踩了三个坑

【转】方今用Timer踩了二个坑,分享一下制止外人继续踩

【转】近来用提姆er踩了一个坑,分享一下防止别人继续踩,timer踩

【转】近日用Timer踩了一个坑,分享一下避免外人继续踩

 

  近来做3个小项目,项目中有三个定期服务,须要向对方按期发送数据,时间间隔是一.伍s,然后就想开了用C#的Timer类,我们领悟Timer

的确格外好用,因为里面有那个家伙性化的start和stop功效,在Timer里面还有3个Interval,就是用来设置时间距离,然后时间距离到了就能够触

发Elapsed事件,大家只要求把callback函数注册到那些事件就足以了,假诺Interval到了就能够触发Elapsed,貌似1切看起来很任其自流,可是

有某个早晚要留心,callback函数本人施行也是内需时日的,恐怕这几个时间是1s,二s也许更长日子,而timer类却任凭那个,它小心一.5s触发一下

Elapsed,那就导致了自身的callback恐怕还从未施行完,下三个callback又起来实施了,也就产生了从未有过高达本人预期的一.伍s的功效,并且还现出了

三个要命严重的主题材料,那正是线程激增,十分恐惧。

 

   下面比如,为了简化一下,笔者就定义五个task职分,当然项目中是几个task任务一起跑的。

 

壹:难点发生

   为了具备更加高的狡猾,作者定义了2个CustomTimer类承接自Timer,然后里面能够放些Task要跑的数目,这里就定义一个Queue。

 1 namespace Sample
 2 {
 3     class Program
 4     {
 5         static void Main(string[] args)
 6         {
 7             TimerCustom timer = new TimerCustom();
 8 
 9             timer.Interval = 1500;
10 
11             timer.Elapsed  = (obj, evt) =>
12             {
13                 TimerCustom singleTimer = obj as TimerCustom;
14 
15                 if (singleTimer != null)
16                 {
17                     if (singleTimer.queue.Count != 0)
18                     {
19                         var item = singleTimer.queue.Dequeue();
20 
21                         Send(item);
22                     }
23                 }
24             };
25 
26             timer.Start();
27 
28             Console.Read();
29         }
30 
31         static void Send(int obj)
32         {
33             //随机暂定8-10s
34             Thread.Sleep(new Random().Next(8000, 10000));
35 
36             Console.WriteLine("当前时间:{0},定时数据发送成功!", DateTime.Now);
37         }
38     }
39 
40     class TimerCustom : System.Timers.Timer
41     {
42         public Queue<int> queue = new Queue<int>();
43 
44         public TimerCustom()
45         {
46             for (int i = 0; i < short.MaxValue; i  )
47             {
48                 queue.Enqueue(i);
49             }
50         }
51     }
52 }

图片 1

图片 2

 

2:消除方法

1.  从上海体育地方看,在三个职务的意况下就已经有十四个线程了,并且在二一s的时候有三个线程同时实行了,作者的率先反馈正是想怎么把后续实行callback的

线程踢出去,约等于承接保险当前仅让四个线程在用callback,三个在推行,一个在守候推行,假如第2个线程的callback未有推行完,后续借使来了第一

个线程的话,作者就把那第二个线程直接踢出去,直到第1个callback施行完后,才同意第玖个线程进来并伺机实行callback,然后曾今的第3个线程开

始试行callback,后续的就以此类推。。。

下一场作者就想开了用lock机制,在customTimer中加进lockMe,lockNum,isFirst字段,用lockMe来锁住,用lockNum来踢当前剩下的要试行callback

的线程,用isFirst来判定是否率先次实施该callback,后续callback的线程必须先等待壹.五s再施行。

 1 namespace Sample
 2 {
 3     class Program
 4     {
 5         static void Main(string[] args)
 6         {
 7             TimerCustom timer = new TimerCustom();
 8 
 9             timer.Interval = 1500;
10 
11             timer.Elapsed  = (obj, evt) =>
12             {
13                 TimerCustom singleTimer = obj as TimerCustom;
14 
15                 if (singleTimer != null)
16                 {
17                     //如果当前等待线程>2,就踢掉该线程
18                     if (Interlocked.Read(ref singleTimer.lockNum) > 2)
19                         return;
20 
21                     Interlocked.Increment(ref singleTimer.lockNum);
22 
23                     //这里的lock只能存在一个线程等待
24                     lock (singleTimer.lockMe)
25                     {
26                         if (!singleTimer.isFirst)
27                         {
28                             Thread.Sleep((int)singleTimer.Interval);
29                         }
30 
31                         singleTimer.isFirst = false;
32 
33                         if (singleTimer.queue.Count != 0)
34                         {
35                             var item = singleTimer.queue.Dequeue();
36 
37                             Send(item);
38 
39                             Interlocked.Decrement(ref singleTimer.lockNum);
40                         }
41                     }
42                 }
43             };
44 
45             timer.Start();
46 
47             Console.Read();
48         }
49 
50         static void Send(int obj)
51         {
52             Thread.Sleep(new Random().Next(8000, 10000));
53 
54             Console.WriteLine("当前时间:{0},邮件发送成功!", DateTime.Now);
55         }
56     }
57 
58     class TimerCustom : System.Timers.Timer
59     {
60         public Queue<int> queue = new Queue<int>();
61 
62         public object lockMe = new object();
63 
64         public bool isFirst = true;
65 
66         /// <summary>
67         /// 为保持连贯性,默认锁住两个
68         /// </summary>
69         public long lockNum = 0;
70 
71         public TimerCustom()
72         {
73             for (int i = 0; i < short.MaxValue; i  )
74             {
75                 queue.Enqueue(i);
76             }
77         }
78     }
79 }

 

 

图片 3

图片 4

从图中可以见见,已经未有一样秒出现重复职分的出殡和埋葬情形了,并且线程也给压制下去了,乍一看效果不是很精通,然而那是在贰个任务的场合

下的现象,义务越来越多就越显明了,所以那一个就高达本身要的功用。

 

二. 从上边的化解方案来看,其实我们的思量已经被难点束缚住了,当时本人也是那样,究竟坑出来了,就务须来填坑,既然在callback中冒出线程

  蜂拥的气象,作者本来要想艺术管制了,其实那也没怎么错,等难题一挥而就了再回头思索下时,大家会意识作品开首说的Timer类有强劲的Stop和

   Start作用,所以。。。。这一年想想就跳出来了,何不在callback试行的时候把Timer关掉,实行完callback后再把Timer开启,那样不就

   能够消除难点吧?好吧,说干就干。

 1 namespace Sample
 2 {
 3     class Program
 4     {
 5         static void Main(string[] args)
 6         {
 7             TimerCustom timer = new TimerCustom();
 8 
 9             timer.Interval = 1500;
10 
11             timer.Elapsed  = (obj, evt) =>
12             {
13                 TimerCustom singleTimer = obj as TimerCustom;
14 
15                 //先停掉
16                 singleTimer.Stop();
17 
18                 if (singleTimer != null)
19                 {
20                     if (singleTimer.queue.Count != 0)
21                     {
22                         var item = singleTimer.queue.Dequeue();
23 
24                         Send(item);
25 
26                         //发送完成之后再开启
27                         singleTimer.Start();
28                     }
29                 }
30             };
31 
32             timer.Start();
33 
34             Console.Read();
35         }
36 
37         static void Send(int obj)
38         {
39             Thread.Sleep(new Random().Next(8000, 10000));
40 
41             Console.WriteLine("当前时间:{0},邮件发送成功!", DateTime.Now);
42         }
43     }
44 
45     class TimerCustom : System.Timers.Timer
46     {
47         public Queue<int> queue = new Queue<int>();
48 
49         public object lockMe = new object();
50 
51         /// <summary>
52         /// 为保持连贯性,默认锁住两个
53         /// </summary>
54         public long lockNum = 0;
55 
56         public TimerCustom()
57         {
58             for (int i = 0; i < short.MaxValue; i  )
59             {
60                 queue.Enqueue(i);
61             }
62         }
63     }
64 }

图片 5

 

从图中能够见见,难题一样获得缓慢解决,而且更轻巧,精妙。

末了总计一下:化解难点的思维很要紧,可是如若跳出思维站到更加高的抽象档次上思量难点一般也很贵重。。。

 

【转】近期用Timer踩了三个坑,分享一下幸免外人继续踩 近年来做三个小项...

 

  方今做三个小品种,项目中有2个定期服务,要求向对方定时发送数据,时间间隔是1.⑤s,然后就悟出了用C#的Timer类,大家知道Timer

实在足够好用,因为内部有万分人性化的start和stop作用,在Timer里面还有一个Interval,正是用来设置时间间隔,然后时间距离到了就会触

发Elapsed事件,我们只必要把callback函数注册到这些事件就足以了,如若Interval到了就能够触发Elapsed,貌似一切看起来很任天由命,可是

有一点决然要留意,callback函数自个儿试行也是亟需时日的,可能那些时刻是1s,二s恐怕更加长日子,而timer类却不管这一个,它小心1.伍s触发一下

Elapsed,这就产生了小编的callback或然还尚未进行完,下一个callback又起先实施了,也就招致了未有到达自身料想的1.5s的法力,并且还冒出了

一个可怜沉痛的主题材料,那正是线程激增,11分害怕。

 

   上面举个例证,为了简化一下,作者就定义二个task职责,当然项目中是多少个task职务一齐跑的。

 

一:难题发出

   为了具有越来越高的灵活性,小编定义了一个CustomTimer类承接自Timer,然后中间能够放些Task要跑的多少,这里就定义3个Queue。

 1 namespace Sample
 2 {
 3     class Program
 4     {
 5         static void Main(string[] args)
 6         {
 7             TimerCustom timer = new TimerCustom();
 8 
 9             timer.Interval = 1500;
10 
11             timer.Elapsed  = (obj, evt) =>
12             {
13                 TimerCustom singleTimer = obj as TimerCustom;
14 
15                 if (singleTimer != null)
16                 {
17                     if (singleTimer.queue.Count != 0)
18                     {
19                         var item = singleTimer.queue.Dequeue();
20 
21                         Send(item);
22                     }
23                 }
24             };
25 
26             timer.Start();
27 
28             Console.Read();
29         }
30 
31         static void Send(int obj)
32         {
33             //随机暂定8-10s
34             Thread.Sleep(new Random().Next(8000, 10000));
35 
36             Console.WriteLine("当前时间:{0},定时数据发送成功!", DateTime.Now);
37         }
38     }
39 
40     class TimerCustom : System.Timers.Timer
41     {
42         public Queue<int> queue = new Queue<int>();
43 
44         public TimerCustom()
45         {
46             for (int i = 0; i < short.MaxValue; i  )
47             {
48                 queue.Enqueue(i);
49             }
50         }
51     }
52 }

图片 6

图片 7

 

贰:解决办法

一.  从上海教室看,在七个职责的气象下就早已有十四个线程了,并且在二壹s的时候有三个线程同时实行了,笔者的首先影响就是想怎么把后续推行callback的

线程踢出去,相当于保证当前仅让七个线程在用callback,四个在实施,一个在伺机实施,就算第五个线程的callback未有施行完,后续如果来了第贰

个线程的话,小编就把那第七个线程直接踢出去,直到第三个callback推行完后,才同意第一个线程进来并等候实践callback,然后曾今的第二个线程开

始实施callback,后续的就就那样类推。。。

下一场本人就悟出了用lock机制,在customTimer中追加lockMe,lockNum,isFirst字段,用lockMe来锁住,用lockNum来踢当前剩余的要推行callback

的线程,用isFirst来决断是否首先次实行该callback,后续callback的线程必须先等待一.五s再实行。

 1 namespace Sample
 2 {
 3     class Program
 4     {
 5         static void Main(string[] args)
 6         {
 7             TimerCustom timer = new TimerCustom();
 8 
 9             timer.Interval = 1500;
10 
11             timer.Elapsed  = (obj, evt) =>
12             {
13                 TimerCustom singleTimer = obj as TimerCustom;
14 
15                 if (singleTimer != null)
16                 {
17                     //如果当前等待线程>2,就踢掉该线程
18                     if (Interlocked.Read(ref singleTimer.lockNum) > 2)
19                         return;
20 
21                     Interlocked.Increment(ref singleTimer.lockNum);
22 
23                     //这里的lock只能存在一个线程等待
24                     lock (singleTimer.lockMe)
25                     {
26                         if (!singleTimer.isFirst)
27                         {
28                             Thread.Sleep((int)singleTimer.Interval);
29                         }
30 
31                         singleTimer.isFirst = false;
32 
33                         if (singleTimer.queue.Count != 0)
34                         {
35                             var item = singleTimer.queue.Dequeue();
36 
37                             Send(item);
38 
39                             Interlocked.Decrement(ref singleTimer.lockNum);
40                         }
41                     }
42                 }
43             };
44 
45             timer.Start();
46 
47             Console.Read();
48         }
49 
50         static void Send(int obj)
51         {
52             Thread.Sleep(new Random().Next(8000, 10000));
53 
54             Console.WriteLine("当前时间:{0},邮件发送成功!", DateTime.Now);
55         }
56     }
57 
58     class TimerCustom : System.Timers.Timer
59     {
60         public Queue<int> queue = new Queue<int>();
61 
62         public object lockMe = new object();
63 
64         public bool isFirst = true;
65 
66         /// <summary>
67         /// 为保持连贯性,默认锁住两个
68         /// </summary>
69         public long lockNum = 0;
70 
71         public TimerCustom()
72         {
73             for (int i = 0; i < short.MaxValue; i  )
74             {
75                 queue.Enqueue(i);
76             }
77         }
78     }
79 }

 

 

图片 8

图片 9

从图中能够看来,已经未有同样秒出现重复任务的出殡和埋葬意况了,并且线程也给压制下去了,乍一看效果不是很备受瞩目,可是那是在叁个义务的情形

下的境况,义务更加多就越显明了,所以这些就直达本身要的成效。

 

二. 从上面的解决方案来看,其实大家的沉思已经被难点束缚住了,当时自身也是如此,毕竟坑出来了,就无法不来填坑,既然在callback中冒出线程

  蜂拥的地方,小编自然要想艺术管制了,其实那也没怎么错,等难题化解了再回头思虑下时,大家会开采小说开始说的Timer类有无往不胜的Stop和

   Start功效,所以。。。。这一年想想就跳出来了,何不在callback试行的时候把Timer关掉,推行完callback后再把Timer开启,那样不就

   能够消除难点啊?好啊,说干就干。

 1 namespace Sample
 2 {
 3     class Program
 4     {
 5         static void Main(string[] args)
 6         {
 7             TimerCustom timer = new TimerCustom();
 8 
 9             timer.Interval = 1500;
10 
11             timer.Elapsed  = (obj, evt) =>
12             {
13                 TimerCustom singleTimer = obj as TimerCustom;
14 
15                 //先停掉
16                 singleTimer.Stop();
17 
18                 if (singleTimer != null)
19                 {
20                     if (singleTimer.queue.Count != 0)
21                     {
22                         var item = singleTimer.queue.Dequeue();
23 
24                         Send(item);
25 
26                         //发送完成之后再开启
27                         singleTimer.Start();
28                     }
29                 }
30             };
31 
32             timer.Start();
33 
34             Console.Read();
35         }
36 
37         static void Send(int obj)
38         {
39             Thread.Sleep(new Random().Next(8000, 10000));
40 
41             Console.WriteLine("当前时间:{0},邮件发送成功!", DateTime.Now);
42         }
43     }
44 
45     class TimerCustom : System.Timers.Timer
46     {
47         public Queue<int> queue = new Queue<int>();
48 
49         public object lockMe = new object();
50 
51         /// <summary>
52         /// 为保持连贯性,默认锁住两个
53         /// </summary>
54         public long lockNum = 0;
55 
56         public TimerCustom()
57         {
58             for (int i = 0; i < short.MaxValue; i  )
59             {
60                 queue.Enqueue(i);
61             }
62         }
63     }
64 }

图片 10

 

从图中可以看到,难点同样赢得消除,而且更简便易行,精妙。

末尾计算一下:化解难点的沉思很怜惜,不过一旦跳出思维站到越来越高的抽象档案的次序上考虑难点一般也很难得。。。

 

本文由必发88手机版发布,转载请注明来源:享用一下防止外人继续踩,近日用Timer踩了三个坑