2017-01-01 74 views
0

我在C#中有一個控制檯服務器,它在while(true)循環中保持運行。但即使它沒有做任何事情,CPU佔用> 50%。我嘗試過Thread.Sleep它的工作!不再吃我的CPU,但它不會在指定的確切時間內恢復,並且不被認爲是良好的做法。我做對了嗎?或者,除了使用while(true)和Thread.Sleep之外,還有其他方法嗎?如何在C#中創建應用程序循環#

+2

什麼是循環在做什麼?通常你會等待某種事件發生,而不是做一個繁忙的循環或者使用'Thread.Sleep()' –

+0

你想讓你的循環執行或暫停的條件是什麼? –

+0

這是服務器的主循環。它將處理所有的遊戲邏輯。它還需要檢查是否有掛起的連接。所以它不聽任何事件。它觸發事件。但是如果這個循環沒有做任何事情或者負載不足,它不僅會加速遊戲的速度(可以處理這個),而且它也會佔用大於50%的CPU,基本上什麼也不做。 – KidCoder

回答

0

當你要暫停一會兒線程無需耗費CPU的資源,您通常使用一些WaitHandle(如AutoResetEventManualResetEvent),並調用它的WaitOne()方法來掛起線程,直到事件應該喚醒它發生(例如,按鍵,新的網絡連接到達,異步操作完成等)。

要定期喚醒線程,可以使用計時器。我不知道.NET Framework中有任何計時器,它提供了WaitHandle(當然,您可以自己輕鬆創建這樣的類),因此必須使用Timer並在其回調的每個記號中手動調用AutoResetEvent.Set()。

private static AutoResetEvent TimerWaitHandle = new AutoResetEvent(false); 

static void Main() 
{ 
    // Initialize timer 
    var timerPeriod = TimeSpan.FromMilliseconds(500); 
    Timer timer = new Timer(TimerCallback, null, timerPeriod, timerPeriod); 

    while(true) 
    { 
     // Here perform your game logic 

     // Suspend main thread until next timer's tick 
     TimerWaitHandle.WaitOne(); 

     // It is sometimes useful to wake up thread by more than event, 
     // for example when new user connects etc. WaitHandle.WaitAny() 
     // allows you to wake up thread by any event, whichever occurs first. 
     //WaitHandle.WaitAny(new[] { TimerWaitHandle, tcpListener.BeginAcceptSocket(...).AsyncWaitHandle }); 
    } 
} 

static void TimerCallback(Object state) 
{ 
    // If possible, you can perform desired game logic here, but if you 
    // need to handle it on main thread, wake it using TimerWaitHandle.Set() 

    TimerWaitHandle.Set(); 
} 
0

我無法評論,所以我會把它放在這裏。

理論上與Thread.sleep(1)它不會使用太多的CPU。 您可以從此問題中獲得更多信息:What is the impact of Thread.Sleep(1) in C#?

+0

是的,我不吃CPU,但問題是:有沒有更好的方法來做到這一點,或者這是我不聽任何事件的唯一方法。 – KidCoder

0

您可以使用System.Threading.Timer類。它提供了一種機制,用於以指定的時間間隔在線程池線程上執行方法。

public void Start() 
{ 
} 

int dueTime = 1000; 
int periodTS = 5000; 
System.Threading.Timer myTimer = new System.Threading.Timer(new TimerCallback(Start), null, dueTime, periodTS); 

這將調用從調用它,並且開始後1秒後開始方法,每5秒鐘後調用。

你可以閱讀更多關於Timerhere

+0

我試了一下,它的工作,但我的主線程結束執行和程序停止。這再次需要我睡覺的線程:( – KidCoder

+0

@KidCoder你不能只是啓動一個計時器,然後讓主線程返回,這將退出程序,因爲你發現了。主線程可以做其他事情;或者,如果它沒有任何關係,它可以等待定時器,一般來說,如果你打電話給'睡眠'這是一個設計不好的標誌 – eurotrash

+0

如何等待沒有while循環的定時器?我知道Thread.Sleep被認爲是這就是爲什麼我問這個問題,知道是否有更好的方法來做到這一點。 – KidCoder