gpt4 book ai didi

c# - 使用信号量而不是 while 循环。这是好事还是坏事?

转载 作者:太空狗 更新时间:2023-10-29 21:46:32 24 4
gpt4 key购买 nike

我有一个在它自己的线程中运行的进程,可以在不阻塞的情况下启动/停止。这最终将进入 Windows 服务,但我现在在控制台应用程序中进行设置,直到它完全充实。

调用 Start() 后,我希望主程序线程阻塞,直到按下 Ctrl-C。我知道这会起作用:

public static void Main(string[] args)
{
bool keepGoing = true;

var service = new Service();

System.Console.TreatControlCAsInput = false;

System.Console.CancelKeyPress += delegate(object sender, ConsoleCancelEventArgs e)
{
e.Cancel = true;
service.Stop();
keepGoing = false; // Break the while loop below
};

service.Start();

while( keepGoing )
{
Thread.Sleep(100); // 100 is arbitrary
}

}

但是,我发现标志和任意 sleep 值很麻烦。我知道 CPU 成本在 while 循环中几乎为 0,但我宁愿有一个“硬” block ,它会在 Ctrl-C 处理程序完成后立即释放。我设计了以下内容,使用信号量进行阻塞,直到匿名 Ctrl-C 处理程序完成:

public static void Main(string[] args)
{
var service = new Service();

var s = new Semaphore(1, 1);

System.Console.TreatControlCAsInput = false;

System.Console.CancelKeyPress += delegate(object sender, ConsoleCancelEventArgs e)
{
e.Cancel = true;
service.Stop();
s.Release(); // This will allow the program to conclude below
};

service.Start();

s.WaitOne(); // This will not block
s.WaitOne(); // This will block w/o CPU usage until the sempahore is released

}

这是一个糟糕的设计吗?是不是矫枉过正?危险吗?

编辑:

我还连接 AppDomain.CurrentDomain.UnhandledException 如下:

AppDomain.CurrentDomain.UnhandledException += delegate {
service.Stop();
s.Release();
};

编辑第二个:

我应该指出,Stop() 方法在退出时被调用是至关重要的。 @Adam Ralph 有一个完美的混合控制台/服务模式,但在回答问题时没有此信息。

最佳答案

我们的一些应用程序也有类似的要求。它们是 Windows 服务,但为了调试,我们通常希望将它们作为控制台应用程序运行。此外,我们通常很早就将新应用程序编码为 Windows 服务,但通常不想等到后来(一旦我们证明了概念等)才将它们作为服务实际运行。

这是我们使用的模式:-

using (var service = new Service())
{
if (Environment.UserInterActive)
{
service.Start();
Thread.Sleep(Timeout.Infinite);
}
else
{
ServiceBase.Run(service);
}
}

让线程无限休眠看似效率低下,但这仅适用于调试场景,冗余线程不消耗 CPU 时间,只是一些内存(大约 1MB),主要由分配给线程的堆栈空间组成。该进程仍然可以使用 Ctrl+C 或关闭命令窗口退出。

-- 编辑--

如果您发现在按下 Ctrl+C 时未调用 service.Dispose()(即发生了粗鲁的中止)并且调用了 Dispose()是至关重要的,那么我想你可以明确地这样做:-

using (var service = new Service())
{
if (Environment.UserInterActive)
{
Console.CancelKeyPress += (sender, e) => service.Dispose();
service.Start();
Thread.Sleep(Timeout.Infinite);
}
else
{
ServiceBase.Run(service);
}
}

注意Stop()应该封装在Dispose()中。

关于c# - 使用信号量而不是 while 循环。这是好事还是坏事?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8347008/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com