Таймер высокого разрешения в C #
10724 просмотра
3 ответа
Есть ли таймер высокого разрешения, который вызывает событие каждый раз, когда таймер истекает, как System.Timer
класс? Мне нужен таймер высокого разрешения для Elapse
каждой мс.
Я продолжаю сталкиваться с сообщениями, которые объясняют, что секундомер может измерять высокое разрешение, но я не хочу измерять время, я хочу создать интервал в 1 мс.
Что-то есть в .NET или я собираюсь написать свой собственный таймер высокого разрешения?
Автор: bas Источник Размещён: 12.11.2019 09:39Ответы (3)
12 плюса
Там нет ничего встроенного в .NET Framework, о котором я знаю. В Windows есть механизм для событий таймера высокого разрешения через API мультимедийного таймера . Ниже приведен краткий пример, который я, похоже, выполнил. Есть также , кажется, быть хорошим примером здесь .
Отмечу, что этот API изменяет общесистемные настройки, которые могут ухудшить производительность системы, поэтому покупатель остерегается. В целях тестирования я бы порекомендовал отслеживать частоту срабатывания таймера, чтобы убедиться, что синхронизация аналогична устройству, которое вы пытаетесь смоделировать. Поскольку Windows не является операционной системой реального времени, загрузка вашей системы может привести к задержке таймера MM, что приведет к промежуткам в 100 мс, которые содержат 100 событий в быстрой последовательности, а не к 100 событиям, разнесенным на 1 мс. Некоторое дополнительное чтение на таймерах MM.
class Program
{
static void Main(string[] args)
{
TestThreadingTimer();
TestMultimediaTimer();
}
private static void TestMultimediaTimer()
{
Stopwatch s = new Stopwatch();
using (var timer = new MultimediaTimer() { Interval = 1 })
{
timer.Elapsed += (o, e) => Console.WriteLine(s.ElapsedMilliseconds);
s.Start();
timer.Start();
Console.ReadKey();
timer.Stop();
}
}
private static void TestThreadingTimer()
{
Stopwatch s = new Stopwatch();
using (var timer = new Timer(o => Console.WriteLine(s.ElapsedMilliseconds), null, 0, 1))
{
s.Start();
Console.ReadKey();
}
}
}
public class MultimediaTimer : IDisposable
{
private bool disposed = false;
private int interval, resolution;
private UInt32 timerId;
// Hold the timer callback to prevent garbage collection.
private readonly MultimediaTimerCallback Callback;
public MultimediaTimer()
{
Callback = new MultimediaTimerCallback(TimerCallbackMethod);
Resolution = 5;
Interval = 10;
}
~MultimediaTimer()
{
Dispose(false);
}
public int Interval
{
get
{
return interval;
}
set
{
CheckDisposed();
if (value < 0)
throw new ArgumentOutOfRangeException("value");
interval = value;
if (Resolution > Interval)
Resolution = value;
}
}
// Note minimum resolution is 0, meaning highest possible resolution.
public int Resolution
{
get
{
return resolution;
}
set
{
CheckDisposed();
if (value < 0)
throw new ArgumentOutOfRangeException("value");
resolution = value;
}
}
public bool IsRunning
{
get { return timerId != 0; }
}
public void Start()
{
CheckDisposed();
if (IsRunning)
throw new InvalidOperationException("Timer is already running");
// Event type = 0, one off event
// Event type = 1, periodic event
UInt32 userCtx = 0;
timerId = NativeMethods.TimeSetEvent((uint)Interval, (uint)Resolution, Callback, ref userCtx, 1);
if (timerId == 0)
{
int error = Marshal.GetLastWin32Error();
throw new Win32Exception(error);
}
}
public void Stop()
{
CheckDisposed();
if (!IsRunning)
throw new InvalidOperationException("Timer has not been started");
StopInternal();
}
private void StopInternal()
{
NativeMethods.TimeKillEvent(timerId);
timerId = 0;
}
public event EventHandler Elapsed;
public void Dispose()
{
Dispose(true);
}
private void TimerCallbackMethod(uint id, uint msg, ref uint userCtx, uint rsv1, uint rsv2)
{
var handler = Elapsed;
if (handler != null)
{
handler(this, EventArgs.Empty);
}
}
private void CheckDisposed()
{
if (disposed)
throw new ObjectDisposedException("MultimediaTimer");
}
private void Dispose(bool disposing)
{
if (disposed)
return;
disposed = true;
if (IsRunning)
{
StopInternal();
}
if (disposing)
{
Elapsed = null;
GC.SuppressFinalize(this);
}
}
}
internal delegate void MultimediaTimerCallback(UInt32 id, UInt32 msg, ref UInt32 userCtx, UInt32 rsv1, UInt32 rsv2);
internal static class NativeMethods
{
[DllImport("winmm.dll", SetLastError = true, EntryPoint = "timeSetEvent")]
internal static extern UInt32 TimeSetEvent(UInt32 msDelay, UInt32 msResolution, MultimediaTimerCallback callback, ref UInt32 userCtx, UInt32 eventType);
[DllImport("winmm.dll", SetLastError = true, EntryPoint = "timeKillEvent")]
internal static extern void TimeKillEvent(UInt32 uTimerId);
}
Автор: Mike Zboray
Размещён: 19.07.2014 07:05
0 плюса
Попробуйте создать новое System.Threading.Thread
и использовать System.Threading.Thread.Sleep
.
var thrd = new Syatem.Threading.Thread(() => {
while (true) {
// do something
System.Threading.Thread.Sleep(1); // wait 1 ms
}
});
thrd.Start();
Автор: user3855678
Размещён: 19.07.2014 10:29
0 плюса
Есть вариант: использовать Thread.Sleep(0)
. Попытка вызвать Thread.Sleep(1)
или нанять вызов System.Threading.Timer
всегда сводится к разрешению системного таймера. В зависимости от одного, вероятно, не самая лучшая идея, в конце дня вашему приложению может быть просто запрещено звонить timeBeginPeriod(...)
из winmm.dll.
Следующий код может разрешиться до +/- 10 нс (0,10 мс) на моей машине разработчика (i7q) и может быть выше. Это приведет к серьезной нагрузке на одно из ядер вашего процессора, что увеличит его использование до 100%. Никакого реального замедления ОС не произойдет, код отдает большую часть своего времени процессора, вызывая Thread.Sleep как можно раньше:
var requiredDelayMs = 0.1;
var sw = new System.Diagnostics.Stopwatch();
sw.Start();
while (true)
{
if (sw.Elapsed.TotalMilliseconds >= requiredDelayMs)
{
// call your timer routine
}
Thread.Sleep(0); // setting at least 1 here would involve a timer which we don't want to
}
Для более полной реализации см. Мой другой ответ
Автор: Vitaly Размещён: 03.04.2019 08:16Вопросы из категории :
- c# Преобразовать десятичную в двойную?
- c# Как рассчитать чей-то возраст в C #?
- c# Как вы сортируете словарь по значению?
- c# В чем разница между int и Integer в Java и C #?
- c# Как создать новый экземпляр объекта из Типа
- c# Datatable против Dataset
- timer DateTime.Now лучший способ измерить производительность функции?
- timer Как рассчитать истекшее время события в Java?
- timer Как создать таймер пакетного файла для выполнения / вызова другого пакета в течение дня
- timer В классе с двумя таймерами они выполняются в двух отдельных потоках?
- timer System.currentTimeMillis против System.nanoTime
- timer Сравните, используя Thread.Sleep и Timer для отложенного выполнения
- high-resolution Таймер высокого разрешения в C #
- high-resolution Размещение ложного компонента SWING в Java с помощью монитора 4K
- high-resolution Working with large (over 3000x3000) images in OpenCV, and they don't fit in my screen
- high-resolution Приложение SWT RCP не правильно. Работа на более высоком разрешении
- high-resolution Приложение WPF с веб-браузером и дисплеем высокого разрешения
- high-resolution Поддержка HiDPI в Java Swing для разнообразного внешнего вида