亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 學院 > 開發設計 > 正文

最近用Timer踩了一個坑,分享一下避免別人繼續踩

2019-11-14 16:21:41
字體:
來源:轉載
供稿:網友

 

  最近做一個小項目,項目中有一個定時服務,需要向對方定時發送數據,時間間隔是1.5s,然后就想到了用C#的Timer類,我們知道Timer

確實非常好用,因為里面有非常人性化的start和stop功能,在Timer里面還有一個Interval,就是用來設置時間間隔,然后時間間隔到了就會觸

發Elapsed事件,我們只需要把callback函數注冊到這個事件就可以了,如果Interval到了就會觸發Elapsed,貌似一切看起來很順其自然,但是

有一點一定要注意,callback函數本身執行也是需要時間的,也許這個時間是1s,2s或者更長時間,而timer類卻不管這些,它只顧1.5s觸發一下

Elapsed,這就導致了我的callback可能還沒有執行完,下一個callback又開始執行了,也就導致了沒有達到我預期的1.5s的效果,并且還出現了

一個非常嚴重的問題,那就是線程激增,非??植馈?/p>

 

   下面舉個例子,為了簡化一下,我就定義一個task任務,當然項目中是多個task任務一起跑的。

 

一:問題產生

   為了具有更高的靈活性,我定義了一個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-10s34             Thread.Sleep(new Random().Next(8000, 10000));35 36             Console.WriteLine("當前時間:{0},定時數據發送成功!", DateTime.Now);37         }38     }39 40     class TimerCustom : System.Timers.Timer41     {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.  從上圖看,在一個任務的情況下就已經有14個線程了,并且在21s的時候有兩個線程同時執行了,我的第一反應就是想怎么把后續執行callback的

線程踢出去,也就是保證當前僅讓兩個線程在用callback,一個在執行,一個在等待執行,如果第一個線程的callback沒有執行完,后續如果來了第三

個線程的話,我就把這第三個線程直接踢出去,直到第一個callback執行完后,才允許第三個線程進來并等待執行callback,然后曾今的第二個線程開

始執行callback,后續的就以此類推。。。

然后我就想到了用lock機制,在customTimer中增加lockMe,lockNum,isFirst字段,用lockMe來鎖住,用lockNum來踢當前多余的要執行callback

的線程,用isFirst來判斷是不是第一次執行該callback,后續callback的線程必須先等待1.5s再執行。

 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.Timer59     {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 }

 

 

從圖中可以看到,已經沒有同一秒出現重復任務的發送情況了,并且線程也給壓制下去了,乍一看效果不是很明顯,不過這是在一個任務的情況

下的場景,任務越多就越明顯了,所以這個就達到我要的效果。

 

2. 從上面的解決方案來看,其實我們的思維已經被問題約束住了,當時我也是這樣,畢竟坑出來了,就必須來填坑,既然在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.Timer46     {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 }

 

從圖中可以看到,問題同樣得到解決,而且更簡單,精妙。


最后總結一下:解決問題的思維很重要,但是如果跳出思維站到更高的抽象層次上考慮問題貌似也很難得。。。

 


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
欧美在线免费视频| 日本视频久久久| 91欧美精品午夜性色福利在线| 亚洲人成绝费网站色www| 日韩在线观看网站| 国产精品视频免费在线| 日韩av在线网址| 欧美噜噜久久久xxx| 欧美日韩一区二区在线播放| 成人www视频在线观看| 黄色成人av在线| 国产美女91呻吟求| 欧美刺激性大交免费视频| 亚洲国产一区二区三区四区| 精品久久久久人成| 欧美精品久久久久久久久| 久久精品电影网站| 欧美黑人xxx| 性色av一区二区三区在线观看| 日韩av三级在线观看| 欧洲成人免费aa| 国产日韩在线视频| 日韩av片免费在线观看| 亚洲性生活视频在线观看| 国产精品综合不卡av| 亚洲三级 欧美三级| 亚洲欧洲中文天堂| 亚洲福利视频网站| 欧美一区视频在线| 精品久久久久久久久久久| 欧美日韩爱爱视频| 欧美另类老女人| www.久久久久久.com| 亚洲va男人天堂| 国产精品久久久久久久久久久久久久| 日韩美女中文字幕| 欧美亚洲激情视频| 国产69精品久久久久久| 正在播放欧美视频| 91免费精品视频| 亚洲国产成人久久综合一区| 欧美在线播放视频| 久久99国产精品自在自在app| 成人黄色短视频在线观看| 久久色精品视频| 亚洲欧洲第一视频| 国产综合在线视频| 色诱女教师一区二区三区| www.亚洲人.com| 精品久久久久久久久久ntr影视| 亚洲黄一区二区| 国产欧美一区二区三区久久人妖| 精品亚洲一区二区三区| 97精品免费视频| 97激碰免费视频| 国产日韩在线亚洲字幕中文| 欧美在线视频网| 成人精品一区二区三区| 久久中文精品视频| 精品国产依人香蕉在线精品| 国产日韩精品电影| 日韩欧美中文第一页| 国产精品美女av| 欧美洲成人男女午夜视频| 国语自产在线不卡| 国产日本欧美一区二区三区在线| 九色91av视频| 欧美午夜精品久久久久久人妖| 欧美wwwxxxx| 亚洲人成五月天| 国产aaa精品| 久久成人国产精品| 在线看日韩av| 国产精品狼人色视频一区| 国产一区二区丝袜高跟鞋图片| 亚洲一级一级97网| 成人精品一区二区三区| 91沈先生作品| 欧美激情第1页| 亚洲女人天堂成人av在线| 91欧美激情另类亚洲| 中文字幕九色91在线| 国内揄拍国内精品| 91精品中文在线| 日韩高清不卡av| 欧美性猛交丰臀xxxxx网站| 欧美猛少妇色xxxxx| 久久99久久亚洲国产| 欧美综合在线观看| 欧美大学生性色视频| 91情侣偷在线精品国产| 日韩电视剧在线观看免费网站| 亚洲欧美精品一区二区| 国产97在线亚洲| 日韩美女在线观看一区| 日韩国产在线播放| 日本精品在线视频| 国产精品视频区| 国产亚洲aⅴaaaaaa毛片| 久热精品视频在线| 中文字幕精品网| 欧美激情在线视频二区| 日本精品视频在线观看| 亚洲国产日韩一区| 国产免费久久av| 亚洲美女福利视频网站| 国产欧美精品一区二区| 午夜精品福利在线观看| www.欧美三级电影.com| 欧美在线中文字幕| 91高清视频免费| 欧美性生交xxxxx久久久| xxx欧美精品| 日韩三级影视基地| 高清一区二区三区日本久| 国产日韩欧美另类| 97视频在线观看免费高清完整版在线观看| 不卡av日日日| 国产不卡一区二区在线播放| 亚洲r级在线观看| 91亚洲精华国产精华| 国产精品久久久久久久久久久久久| 国产精品日韩在线| 亚洲国产精彩中文乱码av在线播放| 日韩免费在线电影| 亚洲精品色婷婷福利天堂| 91国产美女在线观看| 亚洲一区二区三区777| 久久久久久一区二区三区| 国产精品一区二区女厕厕| 成人免费黄色网| 亚洲色图17p| 亚洲伊人成综合成人网| 俺去亚洲欧洲欧美日韩| 日韩高清av在线| 丝袜亚洲欧美日韩综合| 97免费在线视频| 欧美精品久久久久a| 日韩日本欧美亚洲| 国产在线视频不卡| 久久久国产91| 欧美另类极品videosbest最新版本| 亚洲免费av网址| 国产精品h在线观看| 日韩欧美综合在线视频| 九九热这里只有精品免费看| 日本高清视频精品| 成人黄色影片在线| 欧美午夜丰满在线18影院| 91精品视频在线| 欧美影院久久久| 精品日本美女福利在线观看| 成人免费网视频| 日韩精品视频免费| 亚洲欧美精品伊人久久| 亚洲色图偷窥自拍| 亚洲激情小视频| 91精品久久久久久久久青青| 亚洲视屏在线播放| 成人国产精品日本在线| 91精品久久久久久久久久入口| 68精品国产免费久久久久久婷婷| 亚洲黄页网在线观看| 国内精品久久久久久|