C# 如何使用替代无限循环或控制台读取键使应用程序保持活动状态?(如有可能)
我需要运行一个包含计时器和多线程的Windows应用程序。此应用程序不需要与用户进行任何交互。我需要运行它,让它活着,直到我决定杀死它。实际上,它将是一个Windows服务。对于测试,我运行无限循环,但这个无限循环似乎不是最好的工作方式 这是我的发射器C# 如何使用替代无限循环或控制台读取键使应用程序保持活动状态?(如有可能),c#,C#,我需要运行一个包含计时器和多线程的Windows应用程序。此应用程序不需要与用户进行任何交互。我需要运行它,让它活着,直到我决定杀死它。实际上,它将是一个Windows服务。对于测试,我运行无限循环,但这个无限循环似乎不是最好的工作方式 这是我的发射器 static void Main() { #if DEBUG new NotificationService().OnStart(); while (true)
static void Main()
{
#if DEBUG
new NotificationService().OnStart();
while (true)
{
Thread.Sleep(600000);
};
#else
ServiceBase[] ServicesToRun;
ServicesToRun = new ServiceBase[]
{
new NotificationService()
};
ServiceBase.Run(ServicesToRun);
#endif
}
我想我的线程。睡眠真的冻结了我所有的进程,甚至冻结了我在NotificationService中创建的时间。下一个代码是my NotificationService的一部分:
protected override void OnStart(string[] args)
{
Logger.Info("Start NotificationSystem");
Timer = new System.Timers.Timer();
Timer.Interval = 12000; // 12 seconds
Timer.Elapsed += new System.Timers.ElapsedEventHandler(OnTimer);
Timer.Start();
}
public void OnStart()
{
OnStart(null);
}
我用OnTimer方法处理我的所有业务。如果您希望能够直接运行您的服务项目,那么为它分配一个控制台是很常见的。您还可以使用它来允许用户通过传递命令行参数来安装服务 您可以阻止此控制台,直到它接收到Ctrl-C:
private static class NativeMethods
{
[DllImport("kernel32.dll")]
public static extern bool AllocConsole();
[DllImport("kernel32.dll")]
public static extern bool FreeConsole();
[DllImport("kernel32.dll")]
public static extern bool AttachConsole(int pid);
}
public static void Main(string[] args)
{
int ret = 0;
if (args.Length == 0)
{
RunService();
}
else
{
if (!NativeMethods.AttachConsole(-1))
{
NativeMethods.AllocConsole();
}
RunConsole();
NativeMethods.FreeConsole();
}
}
private static void RunService()
{
// ...
ServiceBase.Run(...)
// ...
}
private static void RunConsole()
{
var closeEvent = new ManualResetEvent(false);
Console.CancelKeyPress += (o, e) => closeEvent.Set();
new NotificationService().OnStart();
closeEvent.WaitOne();
}
或者,有一个单独的控制台项目来引用您的服务项目并不少见,它只是用于测试
尽管这些解决方案比长时间睡眠的计时器更整洁,但它们将具有相同的阻塞主线程的效果,这在某种程度上是不可避免的。我认为通知服务的问题是另一个问题。我认为您可以使用Quartz.NET和Topshelf来完成这项工作。
下面是一个示例,我希望它能帮助您。在调试模式下,一个更简单的解决方案可能是从用户处获得停止进程的命令:
static void Main()
{
#if DEBUG
var notifService = new NotificationService();
notifService.OnStart();
Console.WriteLine(@"Enter ""quit"" to terminate...");
while ((Console.ReadLine()) != "quit");
notifService.OnStop();
#else
.
.
.
}
是的,但是。。。因为我的进程最终将是一个Windows服务,所以它不是一个控制台应用程序,而是一个Windows应用程序。我没有对Console的引用。@BastienVandamme 1服务项目可以使用Console,如果您使用AllocConsole/FreeConsole/AttachConsole 2,通常使用引用您的服务项目的单独Console应用程序项目进行测试。