Перейти к содержимому



C# Timer microseconds

C# Timer Таймер Timer Problem Milliseconds

  • Авторизуйтесь для ответа в теме
В теме одно сообщение

#1 admin

admin

    Администратор

  • Администраторы
  • 76 сообщений

Отправлено 21 Январь 2014 - 13:18

As far as you know, system timer is not accurate and tick every 15 milliseconds, if you want accurate timer - use this instead of  standard system timer (replace it with), Use interval in microseconds (i.e. you should multiply your interval on 1000. e.g. 20ms = 20000)

Как известно, системный таймер работает с частотой 15 миллисекунд, для некоторых целей (например, проигрывание мультимедиа и т.д.) этого недостаточно, для этих целей используйте данный таймер вместо стандартного. Интервал задается в микросекундах (у стандартного в миллисекундах) т.е. для 20 миллисекунд нужно указать 20000.

The souce link of this example http://www.codeproje...econd-NET-Timer

/// <summary>
/// MicroTimer class
/// </summary>
public class MicroTimer
{
	 public delegate void MicroTimerElapsedEventHandler(
							 object sender,
							 MicroTimerEventArgs timerEventArgs);
	 public event MicroTimerElapsedEventHandler MicroTimerElapsed;
	 System.Threading.Thread _threadTimer = null;
	 long _ignoreEventIfLateBy = long.MaxValue;
	 long _timerIntervalInMicroSec = 0;
	 bool _stopTimer = true;
	 public MicroTimer()
	 {
	 }
	 public MicroTimer(long timerIntervalInMicroseconds)
	 {
		 Interval = timerIntervalInMicroseconds;
	 }
	 public long Interval
	 {
		 get
		 {
			 return System.Threading.Interlocked.Read(
				 ref _timerIntervalInMicroSec);
		 }
		 set
		 {
			 System.Threading.Interlocked.Exchange(
				 ref _timerIntervalInMicroSec, value);
		 }
	 }
	 public long IgnoreEventIfLateBy
	 {
		 get
		 {
			 return System.Threading.Interlocked.Read(
				 ref _ignoreEventIfLateBy);
		 }
		 set
		 {
			 System.Threading.Interlocked.Exchange(
				 ref _ignoreEventIfLateBy, value <= 0 ? long.MaxValue : value);
		 }
	 }
	 public bool Enabled
	 {
		 set
		 {
			 if (value)
			 {
				 Start();
			 }
			 else
			 {
				 Stop();
			 }
		 }
		 get
		 {
			 return (_threadTimer != null && _threadTimer.IsAlive);
		 }
	 }
	 public void Start()
	 {
		 if (Enabled || Interval <= 0)
		 {
			 return;
		 }
		 _stopTimer = false;
		 System.Threading.ThreadStart threadStart = delegate()
		 {
			 NotificationTimer(ref _timerIntervalInMicroSec,
								 ref _ignoreEventIfLateBy,
								 ref _stopTimer);
		 };
		 _threadTimer = new System.Threading.Thread(threadStart);
		 _threadTimer.Priority = System.Threading.ThreadPriority.Highest;
		 _threadTimer.Start();
	 }
	 public void Stop()
	 {
		 _stopTimer = true;
	 }
	 public void StopAndWait()
	 {
		 StopAndWait(System.Threading.Timeout.Infinite);
	 }
	 public bool StopAndWait(int timeoutInMilliSec)
	 {
		 _stopTimer = true;
		 if (!Enabled || _threadTimer.ManagedThreadId ==
			 System.Threading.Thread.CurrentThread.ManagedThreadId)
		 {
			 return true;
		 }
		 return _threadTimer.Join(timeoutInMilliSec);
	 }
	 public void Abort()
	 {
		 _stopTimer = true;
		 if (Enabled)
		 {
			 _threadTimer.Abort();
		 }
	 }
	 void NotificationTimer(ref long timerIntervalInMicroSec,
							 ref long ignoreEventIfLateBy,
							 ref bool stopTimer)
	 {
		 int timerCount = 0;
		 long nextNotification = 0;
		 MicroStopwatch microStopwatch = new MicroStopwatch();
		 microStopwatch.Start();
		 while (!stopTimer)
		 {
			 long callbackFunctionExecutionTime =
				 microStopwatch.ElapsedMicroseconds - nextNotification;
			 long timerIntervalInMicroSecCurrent =
				 System.Threading.Interlocked.Read(ref timerIntervalInMicroSec);
			 long ignoreEventIfLateByCurrent =
				 System.Threading.Interlocked.Read(ref ignoreEventIfLateBy);
			 nextNotification += timerIntervalInMicroSecCurrent;
			 timerCount++;
			 long elapsedMicroseconds = 0;
			 while ((elapsedMicroseconds = microStopwatch.ElapsedMicroseconds)
					 < nextNotification)
			 {
				 System.Threading.Thread.SpinWait(10);
			 }
			 long timerLateBy = elapsedMicroseconds - nextNotification;
			 if (timerLateBy >= ignoreEventIfLateByCurrent)
			 {
				 continue;
			 }
			 MicroTimerEventArgs microTimerEventArgs =
					 new MicroTimerEventArgs(timerCount,
											 elapsedMicroseconds,
											 timerLateBy,
											 callbackFunctionExecutionTime);
			 MicroTimerElapsed(this, microTimerEventArgs);
		 }
		 microStopwatch.Stop();
	 }
}
/// <summary>
/// MicroTimer Event Argument class
/// </summary>
public class MicroTimerEventArgs : EventArgs
{
	 // Simple counter, number times timed event (callback function) executed
	 public int TimerCount { get; private set; }
	 // Time when timed event was called since timer started
	 public long ElapsedMicroseconds { get; private set; }
	 // How late the timer was compared to when it should have been called
	 public long TimerLateBy { get; private set; }
	 // Time it took to execute previous call to callback function (OnTimedEvent)
	 public long CallbackFunctionExecutionTime { get; private set; }
	 public MicroTimerEventArgs(int timerCount,
								 long elapsedMicroseconds,
								 long timerLateBy,
								 long callbackFunctionExecutionTime)
	 {
		 TimerCount = timerCount;
		 ElapsedMicroseconds = elapsedMicroseconds;
		 TimerLateBy = timerLateBy;
		 CallbackFunctionExecutionTime = callbackFunctionExecutionTime;
	 }
}


#2 admin

admin

    Администратор

  • Администраторы
  • 76 сообщений

Отправлено 06 Март 2014 - 02:35

It's better to change this part of code
while ((elapsedMicroseconds = microStopwatch.ElapsedMicroseconds)
										 < nextNotification)
						 {
								 System.Threading.Thread.SpinWait(10);
						 }

to

int wms = (int)timerIntervalInMicroSec / 2000;
wms -= wms / 2;
_threadTimer.Join(wms);
while ((elapsedMicroseconds = microStopwatch.ElapsedMicroseconds) < nextNotification) System.Threading.Thread.SpinWait(10);

because original code uses lots of PC resources in while loop!




Количество пользователей, читающих эту тему: 0

0 пользователей, 0 гостей, 0 скрытых пользователей

Рейтинг@Mail.ru