Служба Windows работает постоянно - PullRequest
52 голосов
/ 01 февраля 2011

Я создал службу Windows с именем ProxyMonitor , и сейчас я нахожусь на стадии, когда служба устанавливается и удаляется так, как я хочу.

Поэтому я выполняю приложение следующим образом:

C:\\Windows\\Vendor\\ProxyMonitor.exe /install

Довольно понятен, а затем я получил services.msc и запускаю службу, но когда я это делаю, я получаю следующее сообщение:

Служба прокси-мониторана локальном компьютере запущен, а затем остановлен.Некоторые службы автоматически останавливаются, если не нужно выполнять никаких действий, например, Службы журналов и оповещений о производительности

Мой код выглядит так:

public static Main(string[] Args)
{
    if (System.Environment.UserInteractive)
    {
        /*
            * Here I have my install logic
        */
    }
    else
    {
        ServiceBase.Run(new ProxyMonitor());
    }
}

И затем в классе ProxyMonitorУ меня есть:

public ProxyMonitor()
{
}

protected override void OnStart(string[] args)
{
    base.OnStart(args);
    ProxyEventLog.WriteEntry("ProxyMonitor Started");

    running = true;
    while (running)
    {
        //Execution Loop
    }
}

и onStop() Я просто изменяю переменную running на false;

Что мне нужно сделать, чтобы Служба была постоянно активной, так как ямне нужно будет отслеживать сеть, мне нужно отслеживать изменения и т.д.


Обновление: 1

protected override void OnStart(string[] args)
{
     base.OnStart(args);
     ProxyEventLog.WriteEntry("ProxyMonitor Started");

     Thread = new Thread(ThreadWorker);
     Thread.Start();
 }

В пределах ThreadWorker у меня есть ProxyEventLogger.WriteEntry("Main thread entered"), который не срабатывает.

Ответы [ 5 ]

143 голосов
/ 01 февраля 2011

Обратный вызов OnStart() должен возвращаться своевременно, поэтому вам захочется создать поток, в котором будет выполняться вся ваша работа.Я бы порекомендовал добавить в ваш класс следующие поля:

using System.Threading;
private ManualResetEvent _shutdownEvent = new ManualResetEvent(false);
private Thread _thread;

Поле _thread будет содержать ссылку на объект System.Threading.Thread, который вы создаете в обратном вызове OnStart().Поле _shutdownEvent содержит конструкцию события системного уровня, которая будет использоваться для подачи сигнала на прекращение работы потока при завершении работы службы.

В обратном вызове OnStart() создайте и запустите поток.

protected override void OnStart(string[] args)
{
     _thread = new Thread(WorkerThreadFunc);
     _thread.Name = "My Worker Thread";
     _thread.IsBackground = true;
     _thread.Start();
}

Вам нужна функция с именем WorkerThreadFunc, чтобы это работало.Он должен соответствовать подписи делегата System.Threading.ThreadStart.

private void WorkerThreadFunc()
{
}

Если вы не включите в эту функцию что-либо, поток запустится, а затем сразу же закроется, так что вы получитеиспользовать некоторую логику, которая, в основном, поддерживает поток, пока вы выполняете свою работу.Это то место, где _shutdownEvent пригодится.

private void WorkerThreadFunc()
{
    while (!_shutdownEvent.WaitOne(0)) {
        // Replace the Sleep() call with the work you need to do
        Thread.Sleep(1000);
    }
}

Цикл while проверяет ManualResetEvent, чтобы определить, установлено оно или нет.Поскольку мы инициализировали объект с false выше, эта проверка возвращает false.Внутри петли мы спим в течение 1 секунды.Вы захотите заменить это работой, которую вам нужно сделать - контролировать настройки прокси и т. Д.

Наконец, при обратном вызове OnStop() вашей службы Windows вы хотите дать сигнал потоку прекратить работу.Это легко, используя _shutdownEvent.

protected override void OnStop()
{
     _shutdownEvent.Set();
     if (!_thread.Join(3000)) { // give the thread 3 seconds to stop
         _thread.Abort();
     }
} 

Надеюсь, это поможет.

6 голосов
/ 01 февраля 2011

Вам необходимо выйти из обработчика OnStart, чтобы сервисный контроллер понял, что ваша служба фактически запущена.Чтобы заставить его работать так, как вы хотите, вы можете запустить таймер, который тикает с интервалом и обрабатывает, когда он тикает.

Редактировать:

Попробуйте поставить System.Diagnostics.Debugger.Launch () в вашем OnStart, чтобы увидеть, что происходит (и поставить точку останова в ThreadWorker).Я бы порекомендовал обернуть это в #if DEBUG, чтобы убедиться, что оно не будет развернуто.

Я также понял, что вы не даете своему Thread имя:

 Thread myThread = new Thread(ThreadWorker);
 myThread.Start();
2 голосов
/ 07 апреля 2017

Пример кода демонстрируется с помощью консольного приложения. надеюсь, это поможет ..

 class Program
{
    private static CancellationTokenSource _cancellationTokenSource;
    private static ManualResetEvent _shutdownEvent = new ManualResetEvent(false);
    private static Thread _serviceStartThread;
    private static Thread _serviceStopThread;

    private static int workcounter = 0;
    static void Main(string[] args)
    {

        _cancellationTokenSource = new CancellationTokenSource();
        _serviceStartThread = new Thread(DoWork);
        _serviceStopThread = new Thread(ScheduledStop);
        StartService();
        StopService();
    }

    private static void StartService()
    {
        _serviceStartThread.Start();

    }

    private static void StopService()
    {
        _serviceStopThread.Start();
    }


    /// <summary>
    /// Triggers a cancellation event for stopping the service in a timely fashion.
    /// </summary>
    private static void ScheduledStop()
    {
        while (!_shutdownEvent.WaitOne(0))
        {
            if (workcounter == 10)
            {
                _cancellationTokenSource.Cancel();
            }
        }
    }

    /// <summary>
    /// Represents a long running Task with cancellation option
    /// </summary>
    private static void DoWork()
    {

        while (!_shutdownEvent.WaitOne(0))
        {
            if(!_cancellationTokenSource.Token.IsCancellationRequested)
            {
                workcounter += 1;
                Console.Write(Environment.NewLine);
                Console.Write("Running...counter: " + workcounter.ToString());
                Thread.Sleep(1000);//Not needed, just for demo..
            }
            else
            {
                Console.Write(Environment.NewLine);
                Console.Write("Recieved cancellation token,shutting down in 5 seconds.. counter: " + workcounter.ToString());
                _shutdownEvent.Set();
                Thread.Sleep(5000);//Not needed, just for demo..
            }

        }
    }
}
2 голосов
/ 01 февраля 2011

Конечно, не добавление цикла while в методе OnStart. Это скажет ОС, что служба не запущена, поскольку она не смогла безопасно выйти из метода OnStart. Я обычно создаю Timer, который включен в методе OnStart. Затем в методе Ticks я вызываю необходимый метод для запуска приложения.

В качестве альтернативы вы можете сделать следующее:

// The main entry point for the process 
static void Main() 
{ 
    System.ServiceProcess.ServiceBase[] ServicesToRun; 
    ServicesToRun = new System.ServiceProcess.ServiceBase[] { new WinService1() }; 
    System.ServiceProcess.ServiceBase.Run(ServicesToRun); 
} 

Для получения дополнительной информации о службах Windows, вы можете получить пример скелета здесь .

0 голосов
/ 01 февраля 2011

Почему бы вам не создать новый проект в своем решении типа Windows Service?Это устанавливает все структуры, которые вам нужно реализовать, включая даже обработчики для событий запуска / остановки службы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...