Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/327.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何使用替代无限循环或控制台读取键使应用程序保持活动状态?(如有可能)_C# - Fatal编程技术网

C# 如何使用替代无限循环或控制台读取键使应用程序保持活动状态?(如有可能)

C# 如何使用替代无限循环或控制台读取键使应用程序保持活动状态?(如有可能),c#,C#,我需要运行一个包含计时器和多线程的Windows应用程序。此应用程序不需要与用户进行任何交互。我需要运行它,让它活着,直到我决定杀死它。实际上,它将是一个Windows服务。对于测试,我运行无限循环,但这个无限循环似乎不是最好的工作方式 这是我的发射器 static void Main() { #if DEBUG new NotificationService().OnStart(); while (true)

我需要运行一个包含计时器和多线程的Windows应用程序。此应用程序不需要与用户进行任何交互。我需要运行它,让它活着,直到我决定杀死它。实际上,它将是一个Windows服务。对于测试,我运行无限循环,但这个无限循环似乎不是最好的工作方式

这是我的发射器

        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应用程序项目进行测试。