2015-11-19 56 views
3

我有一個包含兩個線程的控制檯應用程序,一個正在做重複的耗時工作,另一個正在檢查用戶是否按下ESC鍵。如果按下ESC鍵,耗時的工作線程暫停,將出現「是否確定」消息,如果選擇是,則耗時的工作線程完成其當前循環,然後退出。來自while循環的高CPU使用率,檢查keypress事件

由於while (!breakCurrentOperation(work)) ;循環,我必須檢查按鍵的代碼是否使用了大量的CPU資源。我怎樣才能防止這種情況發生?

代碼:

public void runTimeConsumingWork() 
    { 
     HardWork work = new HardWork(); 

     Thread workerThread = new Thread(() => work.StartWorking()); 
     workerThread.Start(); // Start the hard work thread 

     while (!workerThread.IsAlive) ; // Hault untill Thread becomes Active 

     // Check if the user wants to stop the hard work 
     while (!breakCurrentOperation(work)) ; 

     // Cancle the hard work 
     work.Stop(); 

     // Notify the User 
     UserInterfaceController.WriteToConsole("Operation Cancled..."); 
    } 


    public static bool breakCurrentOperation(HardWork work) 
    { 
     if (Console.KeyAvailable) 
     { 
      var consoleKey = Console.ReadKey(true); 
      if (consoleKey.Key == ConsoleKey.Escape) 
      { 
       work.Pause(); // Pause 
       UserInterfaceController.WriteToConsole("Do you want to stop the current process? \nType s to stop or c to continue."); 
       string input = Console.ReadLine(); 
       if (input == "c" || input == "C") 
       { 
        work.Pause(); // Unpause 
        return false; // Continue 
       } 
       else if (input == "s" || input == "S") 
       { 
        return true; // Break the loop 
       } 
       else 
       { 
        UserInterfaceController.WriteToConsole("Error: Input was not recognized, the current process will now continue. Press Esc to stop the operation."); 
        work.Pause(); // Unpause 
       } 
      } 
     } 
     return false; 
    } 

如果我把在主控制檯UI線程Thread.Sleep(2000),CPU使用率減少,但應用程序停止響應以2秒的延遲。

+0

嘗試'Thread.Sleep(10);'應用程序會感覺響應,但你不會佔用CPU。該任務的另一種方法是在用戶請求停止時將字段布爾「_stopRequested」設置爲true,並在'workerThread'中檢查是否必須停止每個循環週期。 – SimpleVar

+0

這確實有用。我想知道是否有任何方法可以重構此代碼,以便主線程無限期地停止,直到發生按鍵事件時爲止? –

+0

已更新我的評論。在main中添加一個簡單的'ReadLine()',並且它正是你所描述的。 – SimpleVar

回答

3

你是否真的需要不斷地進行投票調查?如果你在一個單獨的線程中等待輸入,只需使用Console.ReadKey。它會阻塞輸入線程,但你的其他線程將繼續處理。你似乎沒有在輸入線程上做其他任何事情,所以阻塞應該不成問題。

+0

這可能是最有意義的答案。投票投票通常是一個壞主意。即使它不是過程密集型的以持續檢查輸入,如果你只是在無限循環中設置你的進程,它會消耗CPU時間,並且如果你的操作系統沒有其他任何東西來安排你只是要檢查輸入數千次一秒。您可以在這裏實現多種併發模型,但在另一個線程上輪詢看起來效率並不高。 – tsturzl

+0

謝謝,這個答案是我所需要的。我有一種感覺,應該阻止「Console.ReadKey」。在你回答之後,我意識到我的'if(Console.KeyAvailable)'繞過了'Console.ReadKey',所以應用程序沒有按照我的預期行事,直到if條件被刪除。 –

0

看起來像你的esc鍵按檢查邏輯運行在由於while循環結束少循環。由於這個功能保持利用系統資源。

爲了克服這個問題,請在使用Thread.Sleep的循環中使用一些延遲。 1秒延遲將提高很多性能。

+0

這感覺就像一些藥店產品商業。 – SimpleVar

+0

不要把睡眠放在你的主線程上,它保持應用程序掛起,因爲你正確地指出 –

+0

保持在子線程的睡眠 –