I'm using Threading.Timer, like:
new System.Threading.Timer(
new System.Threading.TimerCallback(x=>
file.Write(DateTime.Now.ToString())
), null, 0, 600000);
And, for example it starts at 11:00:00, then i get in file:
11:00:00
11:10:00 11:20:00 ... 12:10:00 12:19:59 12:29:59Why? from some time it begins to do such things? I've tried other timers, like Timers开发者_如何学Go.Timer, and winforms Timer, the same situation. It's depressing me.
EDIT: Solution with accuratetimer which posted in the thread, didnt help. What about win32 multimedia timer, can it help?
because the timer mechanism isn't ideal, portion of time is needed each time file.Write(DateTime.Now.ToString() is executed. thus in due time you have a delay in one second, try leaving it for an hour and I guess you'll have 3 second delay then.
I'm not sure whenever System.Threading.Timer can compensate this by tracking execution time, u should check the manual for options
Take a look at System.Timers.Timer class also.
Also try using this
class Timer
{
private Stopwatch sw;
private Thread executor;
private long interval;
public void Start(int intervalInMilliseconds)
{
interval = intervalInMilliseconds;
sw = new Stopwatch();
executor = new Thread(Run);
executor.Start();
}
public void Run()
{
while (true)
{
sw.Start();
Execute();
sw.Stop();
Thread.Sleep((int)(interval - sw.ElapsedMilliseconds));
sw.Reset();
}
}
public void Execute()
{
// Do your code here
}
}
Yes, the timer is subject to being pre-empted by other important tasks. Nowhere is it guaranteed that the timer will execute precisely on the interval you set. It's only an approximate interval because Windows is a multitasking operating system. If the computer is busy doing something else, it won't be able to service your timer message(s) immediately. So the messages get put into a queue, which allows them to be postponed until it can do so.
That's why you should always check for a time value that is equal to or greater than the time you expect. It's guaranteed that less time will never have elapsed, but it's not guaranteed that more time won't have elapsed. The other timer implementations are no different.
The documentation for the timer provided by the Windows API goes into more detail:
An application uses a timer to schedule an event for a window after a specified time has elapsed. Each time the specified interval (or time-out value) for a timer elapses, the system notifies the window associated with the timer. Because a timer's accuracy depends on the system clock rate and how often the application retrieves messages from the message queue, the time-out value is only approximate.
Windows simply doesn't provide timing mechanisms this precise. In 99 out of 100 cases, it's simply not relevant. For that 1 in 100 case, you need a real-time operating system.
If you are willing to sacrifice some CPU time, you can use the multimedia timer (check this out for a sample C# implementation that I used as a basis for my own component).
You will find that its actual accuracy is up to 1 ms, unlike any other .NET timers or custom solutions that will always necessarily rely on the default 15.625 ms Windows timer.
Caveats: (1) I have only been able to successfully create up to 2 instances of this timer in the same AppDomain - with more instances, some of them did not raise the tick events at all (or after a short while), and (2) do monitor the increased CPU load and decide whether the extra accuracy is worth it.
Here is more accurate timer for you:
class AccurateTimer
{
private TimerCallback _Callback;
private TimeSpan _Period;
private bool _IsWorking = true;
public void Stop()
{
_IsWorking = false;
}
public AccurateTimer(TimerCallback callback, int period)
{
_Period = TimeSpan.FromMilliseconds(period);
_Callback = callback;
new Thread(ThreadMethod).Start();
}
private void ThreadMethod()
{
while (_IsWorking)
{
var start = DateTime.Now;
_Callback.BeginInvoke(null, null, null);
Thread.Sleep(_Period - (DateTime.Now - start));
}
}
}
Usage:
class Program
{
static void Main(string[] args)
{
var timer = new AccurateTimer(x => Console.WriteLine(DateTime.Now.ToString("h:mm:ss.fff")), 3000);
Console.ReadKey();
timer.Stop();
}
}
Output:
11:44:46.987
11:44:49.985
11:44:52.985
11:44:55.985
11:44:58.985
11:45:01.985
System.Threading.Timer:
class Program
{
static void Main(string[] args)
{
new System.Threading.Timer(x => Console.WriteLine(DateTime.Now.ToString("h:mm:ss.fff")), null, 0, 3000);
Console.ReadKey();
}
}
Output:
11:50:22.042
11:50:25.040
11:50:28.051
11:50:31.065
11:50:34.073
11:50:37.083
精彩评论