2009-09-29 124 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就開始和停止音樂,這很奏效。

但是,應用程序將接管計算機,因爲共享會導致您的計時關閉,那麼您最好使用計時器。