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

2021-07-04 02:12:07 字數 2788 閱讀 2911

最近做乙個小專案,專案中有乙個定時服務,需要向對方定時傳送資料,時間間隔是1.5s,然後就想到了用c#的timer類,我們知道timer

確實非常好用,因為裡面有非常人性化的start和stop功能,在timer裡面還有乙個interval,就是用來設定時間間隔,然後時間間隔到了就會觸

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

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

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

乙個非常嚴重的問題,那就是執行緒激增,非常恐怖。

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

一:問題產生

為了具有更高的靈活性,我定義了乙個customtimer類繼承自timer,然後裡面可以放些task要跑的資料,這裡就定義乙個queue。

二:解決方法

1.  從上圖看,在乙個任務的情況下就已經有14個執行緒了,並且在21s的時候有兩個執行緒同時執行了,我的第一反應就是想怎麼把後續執行callback的

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

個執行緒的話,我就把這第三個執行緒直接踢出去,直到第乙個callback執行完後,才允許第三個執行緒進來並等待執行callback,然後曾今的第二個執行緒開

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

然後我就想到了用lock機制,在customtimer中增加lockme,locknum,isfirst欄位,用lockme來鎖住,用locknum來踢當前多餘的要執行callback

的執行緒,用isfirst來判斷是不是第一次執行該callback,後續callback的執行緒必須先等待1.5s再執行。

從圖中可以看到,已經沒有同一秒出現重複任務的傳送情況了,並且執行緒也給壓制下去了,乍一看效果不是很明顯,不過這是在乙個任務的情況

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

2. 從上面的解決方案來看,其實我們的思維已經被問題約束住了,當時我也是這樣,畢竟坑出來了,就必須來填坑,既然在callback中出現執行緒

蜂擁的情況,我當然要想辦法管制了,其實這也沒什麼錯,等問題解決了再回頭考慮下時,我們會發現文章開頭說的timer類有強大的stop和

start功能,所以。。。。這個時候思維就跳出來了,何不在callback執行的時候把timer關掉,執行完callback後再把timer開啟,這樣不就

可以解決問題嗎?好吧,說幹就幹。

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

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

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

最近做乙個小專案,專案中有乙個定時服務,需要向對方定時傳送資料,時間間隔是1.5s,然後就想到了用c 的timer類,我們知道timer 確實非常好用,因為裡面有非常人性化的start和stop功能,在timer裡面還有乙個interval,就是用來設定時間間隔,然後時間間隔到了就會觸 發elaps...

最近踩的乙個小坑

最近需要實現乙個業務,大致的內容是為了提高效率,把資料庫中的資訊定時同步到記憶體中,然後使用記憶體查詢,提高效率。然後在實現過程中遇到了乙個問題,需要同步的資訊約9萬條,但是這9w條資料對應了133w個,大概乙個id十幾張吧。儲存這些的時候,遇到了小問題。專案原本使用的結構是 list vin1,1...

踩了乙個基礎 知識的坑

今在開發乙個迴圈增加select 的時候,出現了v model繫結到相同物件,當乙個select改變其他也會隨之改變的問題 頁面操作,1 選擇其中乙個select 2 當選擇後發現上下兩個select 也隨之選中為了同樣的值 think think why 修改某乙個select 其他兩個也會同著更...