設計一個每隔20ms檢查一次狀態的程式,用System.Timers.Timer做測試時發現,前幾次執行timer調用函數的時間相同(把間隔改到1s以上時無此問題),用lock也用(可能是我不太會用lock)。
改為System.Threading.Timer測試發現:
Threading和Timers的timer在小間隔時都存在此問題,分析後初步判斷是初次運行前的間隔時間的問題。
Timers的無法設定初次啟動前間隔所以設定20ms間隔時第一次進入前的間隔也是20ms
Threading的可以設定初次啟動前的間隔,設定較大間隔後啟動,便沒有了初次運行時多線程同時進入的情況。
timerClose = new System.Threading.Timer(new TimerCallback(timerCall), null , 20, 20);//多次進入
timerClose = new System.Threading.Timer(new TimerCallback(timerCall), null , 1000, 20);//正常進入
測試用的代碼:using System;
using System.Collections.Generic;
using System.Windows.Forms;
using System.Timers;
using System.Threading;
namespace WindowsApplication3
{
static class Program
{
/**//// <summary>
/// 應用程式的主進入點。
/// </summary>
[STAThread]
static void Main()
{
//System.Threading.Timer thrTimer = new System.Threading.Timer();
System.Timers.Timer timer = new System.Timers.Timer();
timer.Elapsed += new ElapsedEventHandler(timer_Elapsed);
timer.AutoReset = true;
timer.Interval =20;
System.Threading.Timer timerClose;
//解決初次進入timer調用函數時多線程同時訪問函數的問題
//Threading和Timers的timer都存在此問題分析後初步判斷是初次運行前的間隔時間的問題
//Timers的無法設定初次啟動前間隔所以設定20ms間隔時第一次進入前的間隔也是20ms
//Threading的可以設定初次啟動前的間隔,設定較大間隔後啟動,便沒有了初次運行時多線程同時進入的情況。
//timerClose = new System.Threading.Timer(new TimerCallback(timerCall), null , 1000, 20);
//timerClose = new System.Threading.Timer(new TimerCallback(timerCall), null , 20, 20);
//timer.Start();
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
public static void timer_Elapsed(object sender, ElapsedEventArgs e)
{
Console.Out.WriteLine("system :"+DateTime.Now + " " + DateTime.Now.Millisecond + " "+DateTime .Now.TimeOfDay.TotalMilliseconds );
}
//object oo = new object();
//static int inTimer = 0;
public static void timerCall(object obj)
{
//timerClose.Dispose();
//lock (this)
//if (Interlocked.Exchange(ref inTimer, 1) == 0)
{
//Console.Out.WriteLine(Environment.TickCount);
Console.Out.WriteLine("Threading:" + DateTime.Now + " " + DateTime.Now.Millisecond + " " + DateTime.Now.TimeOfDay.TotalMilliseconds);
//this.Close();
//Interlocked.Exchange(ref inTimer, 0);
}
}
}
}