Я пытаюсь выполнять обратный вызов C# каждые 10 мс с точностью до 1 мс, если это возможно. На данный момент в моем проекте я просто использую цикл вращения и секундомер, и мне удалось достичь желаемого результата с отклонением менее 1 мс, но он потребляет 100% ядра процессора, что не идеально. Я ищу решение, чтобы избежать этого, и наткнулся на тему, в которой рассказывается о методе C CreateTimerQueueTimer, дополнительную информацию можно найти здесь.
Я создал следующий скрипт ниже чтобы проверить это в Unity, но по какой-то причине я не могу получить таймер с интервалом менее 15 мс. Точность выглядит очень хорошей, но мне нужно, чтобы она была ниже 15 мс. Я попытался использовать timeBeginPeriod, как было предложено здесь, но это ничего не изменило. Я делаю что-то не так в своем коде или это неправильный способ?
using System.Runtime.InteropServices;
using System;
using UnityEditor;
using UnityEngine;
public static class TestHighResTimer {
private static readonly string debug_id = "[HighRes Timer]";
private static System.Diagnostics.Stopwatch sw;
private static int count = 0;
private static IntPtr timer = IntPtr.Zero;
[InitializeOnLoadMethod]
private static void Init()
{
//Setup some callback so that we don't crash when editing code, reloading domain ect...
AssemblyReloadEvents.beforeAssemblyReload += Destroy;
EditorApplication.update += StartTimer;
EditorApplication.update += EditorUpdate;
Debug.Log($"{debug_id} Init");
}
private static void Destroy()
{
Debug.Log($"{debug_id} Destroy");
EditorApplication.update -= EditorUpdate;
}
private static void StartTimer()
{
EditorApplication.update -= StartTimer;
Debug.Log($"{debug_id} Start");
//Prepare the stopwatch and count to measure the callback interval
sw = new System.Diagnostics.Stopwatch();
count = 0;
timeBeginPeriod(1); //It is supposed to improved accuracy of timer event but I didn't notice a change...
CreateTimerQueueTimer(out timer, IntPtr.Zero, TimerCallback, IntPtr.Zero, 1, 10, 0); //Start a timer to fire the callback every 10ms
}
private static void EditorUpdate()
{
//We limit the test at 1000 iterations otherwise it will run indefinitely
if(count > 1000)
{
DeleteTimerQueueTimer(IntPtr.Zero, timer, IntPtr.Zero); //Clear the timer
timeEndPeriod(1);
count = 0;
}
}
private static void TimerCallback(IntPtr p, bool b)
{
Debug.Log($"{debug_id} Tick : {sw.Elapsed.TotalMilliseconds} [ms]");
sw.Restart();
count++;
}
public delegate void WaitOrTimerDelegate(IntPtr lpParameter, bool TimerOrWaitFired);
[DllImport("kernel32.dll")]
static extern bool CreateTimerQueueTimer(out IntPtr phNewTimer, IntPtr TimerQueue, WaitOrTimerDelegate Callback,
IntPtr Parameter, uint DueTime, uint Period, uint Flags);
[DllImport("kernel32.dll")]
static extern bool DeleteTimerQueueTimer(IntPtr TimerQueue, IntPtr Timer, IntPtr CompletionEvent);
[DllImport("winmm.dll")]
public static extern uint timeBeginPeriod(int msec);
[DllImport("winmm.dll")]
public static extern uint timeEndPeriod(int msec);
}
Подробнее здесь: https://stackoverflow.com/questions/792 ... queuetimer
C# Unity — таймер высокой точности с использованием TimerQueueTimer ⇐ C#
-
- Похожие темы
- Ответы
- Просмотры
- Последнее сообщение