2015-11-19 35 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

保持在子线程的睡眠 –