C#进程等待毫秒精度

C#进程等待毫秒精度,c#,.net,timer,precision,C#,.net,Timer,Precision,我正在开发一个应用程序(类似于游戏助手),它会在特定的时间间隔向游戏发送击键(您可以指定要按下的键) 问题是我需要以毫秒的精度执行按键事件。经过一些研究,我发现Thread.Sleep的分辨率为20-50毫秒,到目前为止,我能找到的最好的分辨率是使用秒表(),如下所示: cmd_PlayJumps = new DelegateCommand( () => { ActivateWindow(); Stopwatch _timer = new

我正在开发一个应用程序(类似于游戏助手),它会在特定的时间间隔向游戏发送击键(您可以指定要按下的键)

问题是我需要以毫秒的精度执行按键事件。经过一些研究,我发现Thread.Sleep的分辨率为20-50毫秒,到目前为止,我能找到的最好的分辨率是使用秒表(),如下所示:

cmd_PlayJumps = new DelegateCommand(
    () =>
    {
        ActivateWindow();

        Stopwatch _timer = new Stopwatch();
        Stopwatch sw = new Stopwatch();
        double dElapsed = 0;

        //Initial Key Press
        _timer.Start();
        _Keyboard.KeyPress(WindowsInput.Native.VirtualKeyCode.RETURN);

        int iTotalJumps = SelectedLayout.JumpCollection.Count;
            //loop through collection
            for (int iJump = 0; iJump < iTotalJumps - 1; iJump++)
            {
                dElapsed = _timer.Elapsed.TotalMilliseconds;

                sw.Restart();
                while (sw.Elapsed.TotalMilliseconds < SelectedLayout.JumpCollection[iJump + 1].WaitTime -
                    dElapsed)
                {
                    //wait
                }

                _timer.Restart();
                _Keyboard.KeyPress(WindowsInput.Native.VirtualKeyCode.RETURN);
            }

            //final key press
            _Keyboard.KeyPress(WindowsInput.Native.VirtualKeyCode.RETURN);

            _timer.Stop();
            _timer = null;
});
cmd\u PlayJumps=new DelegateCommand(
() =>
{
激活窗口();
秒表_定时器=新秒表();
秒表sw=新秒表();
双脱臼=0;
//初始按键
_timer.Start();
_Keyboard.KeyPress(WindowsInput.Native.VirtualKeyCode.RETURN);
int-iTotalJumps=SelectedLayout.JumpCollection.Count;
//循环收集
对于(int-iJump=0;iJump
由于按键事件的持续时间在0.3-1.5毫秒之间变化,我也会记录下来,以消除偏差

尽管如此,我使用这段代码只能获得60%的准确度,因为即使是StopWatch()也没有那么精确(当然,如果我的代码没有错误的话)


我想知道,如何才能达到至少90%的准确率?

您可以尝试使用ElapsedTicks。它是秒表可以测量的最小单位,您可以使用
Frequency
属性将经过的滴答数转换为秒(当然还有秒的分数)。我不知道它是否比耗用的.totalmillizes好,但值得一试。

问题是你需要幸运,这完全取决于达到.Tick的频率,取决于你的硬件,大约为0.2-2毫秒。要避免这种情况是非常困难的,您可以尝试设置一个高进程优先级来窃取CPU以获取更多的时钟信号。
这可以通过以下方式实现:

  System.Diagnostics.Process.GetCurrentProcess().PriorityClass =     ProcessPriorityClass.High;         
也可以尝试设置

  while (sw.Elapsed.TotalMilliseconds <= SelectedLayout.JumpCollection[iJump + 1].WaitTime - dElapsed)

while(sw.eassed.totalmicrosides我使用
Thread.Sleep
和一个旋转侍者的组合,使它的平均计时未命中0.448毫秒。将线程设置为高优先级不会改变逻辑,因为线程需要运行并持续检查变量

static void Main(string[] args)
{
    Thread.CurrentThread.Priority = ThreadPriority.Highest;
    var timespans = new List<TimeSpan>(50);
    while (timespans.Count < 50)
    {
        var scheduledTime = DateTime.Now.AddSeconds(0.40);
        Console.WriteLine("Scheduled to run at: {0:hh:mm:ss.FFFF}", scheduledTime);
        var wait = scheduledTime - DateTime.Now + TimeSpan.FromMilliseconds(-50);
        Thread.Sleep((int)Math.Abs(wait.TotalMilliseconds));
        while (DateTime.Now < scheduledTime) ;
        var offset = DateTime.Now - scheduledTime;
        Console.WriteLine("Actual:              {0}", offset);
        timespans.Add(offset);

    }
    Console.WriteLine("Average delay: {0}", timespans.Aggregate((a, b) => a + b).TotalMilliseconds / 50);
    Console.Read();
}
static void Main(字符串[]args)
{
Thread.CurrentThread.Priority=ThreadPriority.Highest;
var timespans=新列表(50);
while(timespan.Count<50)
{
var scheduledTime=DateTime.Now.AddSeconds(0.40);
WriteLine(“计划在:{0:hh:mm:ss.FFFF}运行”,scheduledTime);
var wait=scheduledTime-DateTime.Now+TimeSpan.From毫秒(-50);
Sleep((int)Math.Abs(wait.total毫秒));
while(DateTime.Nowa+b.total毫秒/50);
Console.Read();
}
请注意,使用在windows上运行的标准CLR代码无法获得真正的实时代码。垃圾收集器可以介入,甚至在循环周期之间,并开始收集对象,此时很有可能获得不精确的计时


<>你可以通过改变垃圾收集器的方式来减少这种情况发生的机会,直到它在极端低内存的情况下才做大的收集。如果这对你来说还不够,考虑用一种语言来解决上面的解决方案,在这里提供了更好的定时保证(例如C++)。.

问题在于,您需要幸运,这完全取决于达到.Tick的频率,取决于您的硬件,大约为0.2-2 ms。要避免这一点非常困难,您可以尝试设置高进程优先级以窃取CPU以获得更多的Tick。同时尝试设置
(sw.appeased.total毫秒*另一个注释(sry用于套印):设置优先级(如前所述):
System.Diagnostics.Process.GetCurrentProcess().PriorityClass=ProcessPriorityClass.High;
@Johan为什么不将这些注释作为答案发布?@user1666620 ok,可以:)我假设IsHighFrequency是真的?