考虑一个Console应用程序,它在一个单独的线程中启动某些服务。它需要做的就是等待用户按Ctrl + C将其关闭。
以下哪项是更好的方法?
static ManualResetEvent _quitEvent = new ManualResetEvent(false);
static void Main() {
Console.CancelKeyPress += (sender, eArgs) => {
_quitEvent.Set();
eArgs.Cancel = true;
};
// kick off asynchronous stuff
_quitEvent.WaitOne();
// cleanup/shutdown and quit
}
或者,使用Thread.Sleep(1):
static bool _quitFlag = false;
static void Main() {
Console.CancelKeyPress += delegate {
_quitFlag = true;
};
// kick off asynchronous stuff
while (!_quitFlag) {
Thread.Sleep(1);
}
// cleanup/shutdown and quit
}
答案 0 :(得分:58)
总是希望阻止使用while循环,尤其是在强制代码重新检查变量时。它会浪费CPU资源并降低程序速度。
我肯定会说第一个。
答案 1 :(得分:27)
或者,更简单的解决方案就是:
Console.ReadLine();
答案 2 :(得分:12)
您可以这样做(并删除CancelKeyPress
事件处理程序):
while(!_quitFlag)
{
var keyInfo = Console.ReadKey();
_quitFlag = keyInfo.Key == ConsoleKey.C
&& keyInfo.Modifiers == ConsoleModifiers.Control;
}
不确定这是否更好,但我不喜欢在循环中调用Thread.Sleep
的想法。我认为阻止用户输入更清晰。
答案 3 :(得分:9)
我更喜欢使用 Application.Run
static void Main(string[] args) {
//Do your stuff here
System.Windows.Forms.Application.Run();
//Cleanup/Before Quit
}
来自文档:
开始在当前线程上运行标准的应用程序消息循环,没有表单。
答案 4 :(得分:3)
好像你让它变得比你需要的更难。为什么不在你发信号通知停止后只用Join
线程?
class Program
{
static void Main(string[] args)
{
Worker worker = new Worker();
Thread t = new Thread(worker.DoWork);
t.IsBackground = true;
t.Start();
while (true)
{
var keyInfo = Console.ReadKey();
if (keyInfo.Key == ConsoleKey.C && keyInfo.Modifiers == ConsoleModifiers.Control)
{
worker.KeepGoing = false;
break;
}
}
t.Join();
}
}
class Worker
{
public bool KeepGoing { get; set; }
public Worker()
{
KeepGoing = true;
}
public void DoWork()
{
while (KeepGoing)
{
Console.WriteLine("Ding");
Thread.Sleep(200);
}
}
}
答案 5 :(得分:2)
其中第一个是更好的
_quitEvent.WaitOne();
因为在第二个线程中,线程每隔一毫秒唤醒就会转入OS中断,这很昂贵
答案 6 :(得分:0)
你应该像编写Windows服务一样。你永远不会使用while语句,而是使用委托。等待线程处理时通常使用WaitOne() - Thread.Sleep() - 不可取 - 您是否考虑过使用System.Timers.Timer来检查关闭事件?
答案 7 :(得分:0)
还可以基于取消令牌来阻止线程/程序。
token.WaitHandle.WaitOne();
当令牌被取消时,会发出WaitHandle信号。
我已经看到Microsoft.Azure.WebJobs.JobHost使用的这项技术,其中的令牌来自WebJobsShutdownWatcher(结束工作的文件监视程序)的取消令牌源。
这可以控制程序何时结束。