简体   繁体   中英

How can I keep an application alive with alternative to infinite loop or console read key? (if possible)

I need ti run a Windows application that contains timer and multiple thread. This application do not require any interaction with user. I need to run it and keep it alive until I decide to kill it. For real it will be a Windows Service. For testing I run and infinite loop but this infinite loop seems not the best way to work.

Here is my launcher

        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
        }

I think my Thread.Sleep really freeze all my process, even my time I create in NotificationService. This next code is part of 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);
        }

I process all my business in OnTimer method.

If you want to be able to run your service project directly, then it's fairly common to allocate a console for it. You can also use this to allow users to install the service, by passing command-line parameters.

You can block this Console until it receives 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();
}


Alternatively, it's not uncommon to have a separate Console project which references your Service project, which is just used for testing.


Although these solutions are neater than a timer with a long sleep, they will have the same effect of blocking the main thread (which is somewhat unavoidable). I think the problem with your notification service is a separate issue.

I think you can use Quartz.NET and Topshelf for this job. Here's a link and I hope it helps you.

In debug mode a simpler solution might be getting a command from user to stop process:

static void Main()
{
#if DEBUG
    var notifService = new NotificationService();
    notifService.OnStart();

    Console.WriteLine(@"Enter ""quit"" to terminate...");
    while ((Console.ReadLine()) != "quit");

    notifService.OnStop();
#else
.
.
.
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM