2009-09-29 79 views
0

我有一个数据列表和需要处理的时间。时间通常相差大约一秒(或更少)(它们各不相同),但需要在相当接近的时间运行。我曾尝试将线程休眠一小段时间,但在睡眠后恢复一个线程会导致短暂的延迟,这会带来一些开销。有没有一种可靠的方法来获得我需要的相对简单的代码的准确性?以精确的时间间隔执行代码

+0

该方法必须被调用的时间距离多近?在15毫秒内,或更多或更少? – MusiGenesis 2009-09-29 04:26:57

+1

您的需求是硬实时还是软实时? http://en.wikipedia.org/wiki/Real-time_computing#Hard_and_soft_real-time_systems – RossFabricant 2009-09-29 04:28:15

回答

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(); 
    } 
} 
+0

+1 StopWatch类非常准确,即使是2岁的人也可以使用它:)谢谢! – Nippysaurus 2009-09-29 22:59:07

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循环完成最后的< 1/1000秒的延迟。这将为您提供超精确的延迟(精确到10微秒),并且CPU占用率极低。

+0

理想情况下,它不会占用CPU:p – Nippysaurus 2009-09-29 04:17:11

+0

如果您没有将CPU耗尽*时间已过,则您没有保证你可以在计时器*过去时开始执行。即使如此,操作系统可能会在错误的时间将控制权从您的线程中分离出来。 – 2009-09-29 04:21:21

+0

我想你会希望这是'while(now 2009-09-29 06:26:11

2

在多任务操作系统提高你的过程可以帮助的优先级,但除非它的操作系统支持real time你不能在几毫秒的水平做出保证定时精确。

0

如果您绝对需要保持短暂的时间差异,您可能需要查看使用DirectX API。 DirectX 9.0c有一个Managed .NET接口,它可以让你访问高可靠性的时钟。我曾用这个播放一些音乐,我不到1ms就开始和停止音乐,这很奏效。

但是,应用程序将接管计算机,因为共享会导致您的计时关闭,那么您最好使用计时器。