如何保持.NET 控制台应用程序运行?

设想一个控制台应用在一个单独的线程中启动一些服务。它所需要做的就是等待用户按 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
}
61399 次浏览

您总是希望避免使用 while 循环,特别是当您强制代码重新检查变量时。它会浪费 CPU 资源并减慢程序的运行速度。

我肯定会说是第一个。

或者,一个更简单的解决方案是:

Console.ReadLine();

前两个中的第一个比较好

_quitEvent.WaitOne();

因为在第二种情况下,每一毫秒线程都会被唤醒,这会导致操作系统中断,而这是非常昂贵的

您可以这样做(并删除 CancelKeyPress事件处理程序) :

while(!_quitFlag)
{
var keyInfo = Console.ReadKey();
_quitFlag = keyInfo.Key == ConsoleKey.C
&& keyInfo.Modifiers == ConsoleModifiers.Control;
}

不确定这样是否更好,但我不喜欢循环调用 Thread.Sleep的想法。.我认为屏蔽用户输入更简单。

您应该像编写 Windows 服务程序那样进行此操作。您将永远不会使用 while 语句,而是使用委托。通常在等待线程释放时使用 WaitOne ()-Thread。Sleep ()-不可取-你有没有想过使用 System。计时器。使用该事件检查关闭事件的计时器?

看起来你把事情搞得更复杂了。为什么不只是 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);
}
}
}

我更喜欢用 申请,运行

static void Main(string[] args) {


//Do your stuff here


System.Windows.Forms.Application.Run();


//Cleanup/Before Quit
}

来自文件:

在没有窗体的情况下,开始在当前线程上运行标准应用程序消息循环。

还可以基于取消令牌阻塞线程/程序。

token.WaitHandle.WaitOne();

取消令牌时会发出 WaitHandle 信号。

我见过微软使用这种技术。天蓝色。网络工作。JobHost,其中令牌来自 WebJobShutdownWatcher (结束作业的文件监视器)的取消令牌源。

这样就可以控制程序何时结束。

你可以当主人了

    public class Program
{
/// <summary>
/// Application entry point
/// </summary>
/// <param name="args">arguments</param>
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}

HostBuilder 在哪

    public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.UseWindowsService()
.ConfigureServices((_, services) =>
{
})
.ConfigureLogging(config =>
{
config.ClearProviders();
});