中文字幕日韩精品一区二区免费_精品一区二区三区国产精品无卡在_国精品无码专区一区二区三区_国产αv三级中文在线

C#中關(guān)于Timer定時(shí)器重入問題如何解決

C#中關(guān)于Timer定時(shí)器重入問題如何解決?這個(gè)問題可能是我們?nèi)粘W(xué)習(xí)或工作經(jīng)常見到的。希望通過這個(gè)問題能讓你收獲頗深。下面是小編給大家?guī)淼膮⒖純?nèi)容,讓我們一起來看看吧!

成都創(chuàng)新互聯(lián)公司堅(jiān)持“要么做到,要么別承諾”的工作理念,服務(wù)領(lǐng)域包括:成都網(wǎng)站建設(shè)、做網(wǎng)站、企業(yè)官網(wǎng)、英文網(wǎng)站、手機(jī)端網(wǎng)站、網(wǎng)站推廣等服務(wù),滿足客戶于互聯(lián)網(wǎng)時(shí)代的普洱網(wǎng)站設(shè)計(jì)、移動(dòng)媒體設(shè)計(jì)的需求,幫助企業(yè)找到有效的互聯(lián)網(wǎng)解決方案。努力成為您成熟可靠的網(wǎng)絡(luò)建設(shè)合作伙伴!

項(xiàng)目中用到了定時(shí)器隨著服務(wù)啟動(dòng)作定時(shí)任務(wù),按指定的準(zhǔn)點(diǎn)時(shí)間定時(shí)執(zhí)行相關(guān)操作,但是在指定準(zhǔn)點(diǎn)時(shí)間內(nèi)我只想讓它執(zhí)行一次,要避免重入問題的發(fā)生。

首先簡單介紹一下timer,這里所說的timer是指的System.Timers.timer,顧名思義,就是可以在指定的間隔是引發(fā)事件。官方介紹在這里,摘抄如下:

Timer 組件是基于服務(wù)器的計(jì)時(shí)器,它使您能夠指定在應(yīng)用程序中引發(fā) Elapsed 事件的周期性間隔。然后可通過處理這個(gè)事件來提供常規(guī)處理。 
例如,假設(shè)您有一臺關(guān)鍵性服務(wù)器,必須每周 7 天、每天 24 小時(shí)都保持運(yùn)行。 可以創(chuàng)建一個(gè)使用 Timer 的服務(wù),以定期檢查服務(wù)器并確保系統(tǒng)開啟并在運(yùn)行。 
如果系統(tǒng)不響應(yīng),則該服務(wù)可以嘗試重新啟動(dòng)服務(wù)器或通知管理員。
    基于服務(wù)器的 Timer 是為在多線程環(huán)境中用于輔助線程而設(shè)計(jì)的。 
    服務(wù)器計(jì)時(shí)器可以在線程間移動(dòng)來處理引發(fā)的 Elapsed 事件,這樣就可以比 Windows 計(jì)時(shí)器更精確地按時(shí)引發(fā)事件。

那使用這個(gè)計(jì)時(shí)器有啥好處呢?主要因?yàn)樗峭ㄟ^.NET Thread Pool實(shí)現(xiàn)的、輕量、計(jì)時(shí)精確、對應(yīng)用程序及消息沒有特別的要求。

Timer是怎么使用的之前有寫過這篇:C# System.Timers.Timer定時(shí)器的使用和定時(shí)自動(dòng)清理內(nèi)存應(yīng)用

什么叫重入呢?這是一個(gè)有關(guān)多線程編程的概念:程序中,多個(gè)線程同時(shí)運(yùn)行時(shí),就可能發(fā)生同一個(gè)方法被多個(gè)進(jìn)程同時(shí)調(diào)用的情況。當(dāng)這個(gè)方法中存在一些非線程安全的代碼時(shí),方法重入會(huì)導(dǎo)致數(shù)據(jù)不一致的情況。Timer方法重入是指使用多線程計(jì)時(shí)器,一個(gè)Timer處理還沒有完成,到了時(shí)間,另一Timer還會(huì)繼續(xù)進(jìn)入該方法進(jìn)行處理。

關(guān)于定時(shí)器的重入問題解決方法嘗試如下

1、使用鎖lock(Object)的方法來防止重入,表示一個(gè)Timer處理正在執(zhí)行,下一個(gè)Timer發(fā)生的時(shí)候發(fā)現(xiàn)上一個(gè)沒有執(zhí)行完就等待執(zhí)行,適用重入很少出現(xiàn)的場景。在觸發(fā)的方法中加入lock,這樣當(dāng)線程2進(jìn)入觸發(fā)的方法中,發(fā)現(xiàn)已經(jīng)被鎖,會(huì)等待鎖中的代碼處理完在執(zhí)行,代碼如下:

private static System.Timers.Timer aTimer = new System.Timers.Timer();
 private static object loker=new object();
   /// <summary>
        /// 設(shè)置定時(shí)器
        /// </summary>
        public static void SetTimer()
        {
            //讀取配置時(shí)間
            try
            {
                aTimer.Interval = 30000;
                aTimer.Elapsed += new System.Timers.ElapsedEventHandler(OnTimedEvent);
                aTimer.AutoReset = true;//每到指定時(shí)間Elapsed事件是到時(shí)間就觸發(fā)
                aTimer.Enabled = true; //指示 Timer 是否應(yīng)引發(fā) Elapsed 事件。
            }
            catch (Exception ex)
            {
                LogManager.RecordLog(LogType.Error, "ipad數(shù)據(jù)同步出錯(cuò):" +ex.Message,ex);
            }
        }
        private static void OnTimedEvent(Object source, ElapsedEventArgs e)
        {
            //如果當(dāng)前時(shí)間是為配置的準(zhǔn)點(diǎn)時(shí)間就進(jìn)來
            var time =Convert.ToInt32( SynchronousHelper.AppConfig.get_Items("SycTime"));
            if (DateTime.Now.Hour == time && DateTime.Now.Minute == 0)
            {
                //lock,這樣當(dāng)線程2進(jìn)入觸發(fā)的方法中,發(fā)現(xiàn)已經(jīng)被鎖,會(huì)等待鎖中的代碼處理完在執(zhí)行
                lock (loker)
                {
                    LogManager.RecordLog(LogType.Info, "數(shù)據(jù)開始同步時(shí)間:" + e.SignalTime, null);
                    SetTimerStart();
                    System.Threading.Thread.Sleep(60000); //執(zhí)行完越過當(dāng)前分鐘,使整點(diǎn)內(nèi)只能進(jìn)來一次
                }
            }
        }

2.置一個(gè)標(biāo)志,表示一個(gè)Timer處理正在執(zhí)行,下一個(gè)Timer發(fā)生的時(shí)候發(fā)現(xiàn)上一個(gè)沒有執(zhí)行完就放棄(注意這里是放棄,而不是等待哦,看看執(zhí)行結(jié)果就明白啥意思了)執(zhí)行,適用重入經(jīng)常出現(xiàn)的場景。在多線程下給inTimer賦值不夠安全,Interlocked.Exchange提供了一種輕量級的線程安全的給對象賦值的方法(感覺比較高上大,也是比較推薦的一種方法)。

private static System.Timers.Timer aTimer = new System.Timers.Timer();
 private static int inTimer = 0;

        /// <summary>
        /// 設(shè)置定時(shí)器
        /// </summary>
        public static void SetTimer()
        {
            //讀取配置時(shí)間
            try
            {
                aTimer.Interval = 30000; //半分鐘觸發(fā)一次
                aTimer.Elapsed += new System.Timers.ElapsedEventHandler(OnTimedEvent);
                aTimer.AutoReset = true;//每到指定時(shí)間Elapsed事件是到時(shí)間就觸發(fā)
                aTimer.Enabled = true; //指示 Timer 是否應(yīng)引發(fā) Elapsed 事件。
            }
            catch (Exception ex)
            {
                LogManager.RecordLog(LogType.Error, "ipad數(shù)據(jù)同步出錯(cuò):" +ex.Message,ex);
            }
        }
        private static void OnTimedEvent(Object source, ElapsedEventArgs e)
        {
            //如果當(dāng)前時(shí)間是為配置的準(zhǔn)點(diǎn)時(shí)間就進(jìn)來
            var time =Convert.ToInt32( SynchronousHelper.AppConfig.get_Items("SycTime"));
            if (DateTime.Now.Hour == time && DateTime.Now.Minute == 0)
            {
                //inTimer設(shè)置一個(gè)標(biāo)志,表示一個(gè)Timer處理正在執(zhí)行,下一個(gè)Timer發(fā)生的時(shí)候發(fā)現(xiàn)上一個(gè)沒有執(zhí)行完就放棄
                if (Interlocked.Exchange(ref inTimer, 1) == 0)
                {
                    LogManager.RecordLog(LogType.Info, "數(shù)據(jù)開始同步時(shí)間:" + e.SignalTime, null);
                    SetTimerStart();
                    System.Threading.Thread.Sleep(60000); //執(zhí)行完等待越過當(dāng)前分鐘,使整點(diǎn)內(nèi)只能進(jìn)來一次
                    Interlocked.Exchange(ref inTimer, 0);
                }
            }
        }

稍微總結(jié)一下,timer是一個(gè)使用挺簡單的類,拿來即用,這里主要總結(jié)了使用timer時(shí)重入問題的解決,以前也沒思考過這個(gè)問題,解決方案也挺簡單。這里的解決方案同時(shí)也適用多線程的重入問題。

感謝各位的閱讀!看完上述內(nèi)容,你們對C#中關(guān)于Timer定時(shí)器重入問題如何解決大概了解了嗎?希望文章內(nèi)容對大家有所幫助。如果想了解更多相關(guān)文章內(nèi)容,歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道。

標(biāo)題名稱:C#中關(guān)于Timer定時(shí)器重入問題如何解決
標(biāo)題URL:http://www.rwnh.cn/article18/gcggdp.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供做網(wǎng)站、全網(wǎng)營銷推廣企業(yè)建站、域名注冊搜索引擎優(yōu)化、微信小程序

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)

h5響應(yīng)式網(wǎng)站建設(shè)
郁南县| 白沙| 滨海县| 泰宁县| 七台河市| 金乡县| 翁源县| 漾濞| 潞西市| 台南县| 黄平县| 神农架林区| 寿阳县| 大英县| 永登县| 桓仁| 鸡西市| 凤城市| 米脂县| 达尔| 云阳县| 祥云县| 云和县| 吐鲁番市| 岫岩| 松潘县| 邮箱| 黄石市| 花莲市| 理塘县| 兴海县| 安阳县| 游戏| 乌什县| 张家界市| 鄂托克旗| 柯坪县| 思茅市| 雷州市| 襄垣县| 双流县|