以精确的间隔执行代码

时间:2009-09-29 04:12:22

标签: c# .net

我有一个数据列表和需要处理的时间。时间通常约为一秒(或更短)(它们各不相同)但需要在相当接近的时间运行。我已经尝试让线程休眠一小段时间,但是在睡眠后恢复线程会产生一些开销,导致短暂的延迟。有一种可靠的方法可以通过相对简单的代码获得我所需的准确度吗?

5 个答案:

答案 0 :(得分:2)

在多任务操作系统中,提高进程的优先级可能会有所帮助,但除非您的操作系统支持real time,否则无法在几毫秒的时间内精确地进行时序保证。

答案 1 :(得分:1)

如何在单独的线程上使用System.Threading.Timer类?

答案 2 :(得分:1)

尝试使用StopWatch对象。我创建了一个假设的DataAndTime对象

public class DataAndTime
{   
   private string m_Data = "";
   public string Data {
      get { return m_Data; }
      set { m_Data = value; }
   }

   private int m_TimeInMilliSeconds = 0;
   public int TimeInMilliSeconds {
      get { return m_TimeInMilliSeconds; }
      set { m_TimeInMilliSeconds = value; }
   } 
}

其中TimeInMilliSeconds是您希望处理数据列表的精确间隔(以毫秒为单位)。然后我创建了两个对象,一个堆栈和一个秒表:

private Stack<DataAndTime> aStack = new Stack<DataAndTime>();    
private Stopwatch aStopWatch = new Stopwatch()

您可以使用集合或列表而不是堆栈或其他任何内容。我用100个DataAndTime对象填充堆栈:

public void PopulateStack{
    for (int Index = 0; Index <= 100; Index++) {
        DataAndTime NewDataAndTime = new DataAndTime();
        NewDataAndTime.Data = (string)Index + " AS A STRING";
        NewDataAndTime.TimeInMilliSeconds = 1000 - Index;
        aStack.Push(NewDataAndTime);
    }
 } 

这个想法与停止和启动秒表的物理模拟相同,并且在经过的毫秒过去的相关时间之前没有做任何事情。瞧。共约40行代码:

 public void ProcessData{
 {
     while (aStack.Count > 0) {
         aStopWatch.Reset();
         aStopWatch.Start();
         DataAndTime StackPop = aStack.Pop;
         string CallBackData = StackPop.Data;
         int CallBackTime = StackPop.TimeInMilliSeconds;
         while (aStopWatch.ElapsedMilliseconds < CallBackTime) {
         }
         Console.WriteLine("Time elapsed for " + CallBackData + " " + CallBackTime + ":  " + aStopWatch.ElapsedMilliseconds);
         aStopWatch.Stop();
     }
 }

答案 3 :(得分:0)

完全时间开始处理的最可靠方法是阻止到确切的时间。在伪代码中:

futuretime = now + 1 second;
while (now < futuretime)
{
     // do nothing
}
// 1 second has elapsed, start processing

但是,当然,只要你处于while循环中,这就会占用CPU。

或者你可以半途而废,做一个线程睡眠,直到你在目标时间的50+毫秒内,然后才进行阻塞等待。你不会那么多地占用CPU,你可以合理地确定你的线程会在1秒钟到来之前被激活。

This article对Windows API提供的计时功能进行了非常全面的评估。最后,它得出结论:

  

...考虑一个混合方案,你可以调用Sleep(1)...每当你需要传递超过1毫秒的时间,然后只进入QueryPerformanceCounter 100%-busy循环来完成最后一个&lt; ;你需要的延迟的1/1000秒。这将为您提供超精确的延迟(精确到10微秒),并且CPU使用率极低。

答案 4 :(得分:0)

如果您绝对需要在时间上保持较短的时间差异,则可能需要查看使用DirectX API。 DirectX 9.0c具有Managed .NET接口,可以访问高可靠性时钟。我曾经用过这种音乐来播放一些不到1毫秒的音乐来开始和停止音乐,而且效果很好。

但是,应用程序将接管计算机,因为共享将关闭时间,然后您可能也在使用计时器。

相关问题