[英]C# - using Thread.Sleep() to get my cycle run several hundred times per second
我正在開發一個分析實時財務數據的應用程序。 目前我的主要計算周期有以下設計:
long cycle_counter=0;
while (process_data)
{
(analyse data, issue instruction - 5000 lines of straightforwasrd code with computations)
cycle_counter++;
Thread.Sleep(5);
}
當我在我的筆記本(一個Core i5)處理器上運行這個應用程序時,循環每秒運行200-205次 - 這是一種預期的(如果你不打擾為什么它每秒運行超過200次)。
但是當我在具有2個6核Xeon處理器和24 GB快速RAM的“真實”工作站上部署應用程序,並且在大約3秒內加載Win7時,應用程序每秒運行大約67次。
我的問題是:
為什么會這樣?
在這種情況下,如何影響每秒的運行次數?
有沒有更好的解決方案,每秒運行200-1000次循環? 我現在正在考慮刪除Thread.Sleep()(我在這里使用它的方式受到了很多批評)。 有12個內核,我只使用一個內核就可以解決這個問題。 但是我的解決方案有一些缺點嗎?
謝謝你的想法。
你正在采取的方法從根本上被打破了。 輪詢策略通常是一種不好的方法,並且任何時候你出於“我想將剩下的時間片還給操作系統”之外的其他原因進行睡眠時,你可能做錯了什么。
解決問題的更好方法是:
如何使用這些屬性構建隊列是一個着名的問題,稱為生產者/消費者問題。 關於如何執行阻塞生產者 - 消費者隊列的任何許多實現,有很多文章。 我建議找一個現有的調試版,而不是試着寫自己的; 做得對可能很棘手。
睡眠的分辨率由當前的計時器滴答間隔決定,通常為10或15毫秒,具體取決於Windows的版本。 但是,可以通過發出timeBeginPeriod命令來更改此設置。 看到這個答案 。
Windows不是RTOS(實時操作系統),因此您無法准確確定線程何時恢復。 Thread.Sleep(5)
真的意味着“在5ms之后叫醒我”。 實際的休眠時間由特定硬件決定,主要由系統負載決定。 您可以嘗試通過以更高優先級運行應用程序來解決system load
問題。
順便說一句, System.Threading.Timer是一種更好的方法(上面的評論仍然適用)。
檢查計時器的實際頻率 :許多硬件計時器具有實際分辨率
65536 ticks per hour = 65536 / 3600 = 18.204 ticks per second
所謂的“18.2”常數,這就是實際定時器的分辨率為1 / 18.2 = 55 ms的原因 ; 在Sleep(5)
的情況下,它意味着可以是Sleep(0)
或Sleep(55)
具體取決於向上舍入。
不確定這是最好的方法,但另一種方法。
嘗試BlockingCollection,你在生產者中所做的只是添加和睡眠。
然后,消費者可以選擇在需要時全職工作。
這仍然無法解釋為什么更高功率的PC運行更少的周期。
您可以平均每秒運行200次循環嗎?
var delay = TimeSpan.FromMillseconds(5);
while (process_data) {
Console.WriteLine("do work");
var now = DateTime.Now;
if (now < nextDue)
System.Threading.Thread.Sleep(nextDue - now);
nextDue = nextDue.Add(delay);
}
使用這種技術,你的循環會有點磕磕絆絆,但它平均應該沒問題,因為代碼既不依賴於Sleep
的分辨率也不依賴於DateTime.Now
的分辨率。
您甚至可以將此方法與Timer結合使用。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.