Подтвердить что ты не робот

Служба Windows, которая работает периодически

Я пишу службу Windows, которая когда-то запускается, запускается каждые X часов. Процесс, который он завершает, довольно интенсивный, поэтому я хочу использовать фона рабочего. Я использую файл настроек, чтобы хранить оба часа между прогонами и последний раз, когда служба запускалась.

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

Я думал об использовании 2 фоновых работников. Первый рабочий будет частной локальной переменной для службы, которая запускает что-то вроде этого:

while (true)
{
      //create new background worker and run

      Thread.Sleep(Settings.Default.SleepTimeHours * 3600000);
}

с субпользователем, который создает каждую итерацию цикла и уничтожается при завершении. Чтобы поддержать отмену, я думаю, что мне придется иметь локальный экземпляр второго рабочего, доступного в службе, но он будет равен нулю, если процесс в настоящее время не запущен. Когда вторичный работник завершает работу, он отправляет мои отчеты, устанавливает последнее время выполнения в файле настроек, а затем удаляет работника и устанавливает ссылку на null.

Мне интересно, есть ли лучший способ сделать это или передовую практику.

Спасибо

4b9b3361

Ответ 1

Обычно я использую таймер, затем останавливаю его, когда процесс начинает работать.

Вот статья, которая объясняет, как это сделать.

Ответ 2

Это не очень хорошая идея, поскольку вы блокируете поток в течение полного периода "SleepTimeHours", и вы не сможете даже остановить службу тем временем.

Вы можете сделать эту услугу так, чтобы она спала, например. 5 секунд, а затем проверить, вернется ли на это время, и если нет, спящий еще 5 секунд (это даст вам необходимую отзывчивость, если вам нужно остановить службу).

ИЛИ: вам может быть лучше просто написать консольное приложение, которое может быть запланировано с помощью функции "запланированных задач" Windows, для запуска каждые x часов. Таким образом, вы не будете блокировать или использовать какой-либо системный ресурс, если ваше приложение ничего не делает......

Марк

Ответ 4

Как насчет чего-то большего:

    public class LongRunningService : ServiceBase
{
    System.Threading.Thread processThread;
    System.Timers.Timer timer;
    private Boolean Cancel;

    protected override void OnStart(string[] args)
    {
        timer = new Timer(Settings.Default.SleepTimeHours * 3600000);
        timer.Elapsed += new ElapsedEventHandler(timer_Tick);
        timer.Start();

        Cancel = false;
    }

    protected override void OnContinue()
    {
        timer.Start();
    }

    protected override void OnPause()
    {
        timer.Stop();
    }

    protected override void OnStop()
    {
        if (processThread.ThreadState == System.Threading.ThreadState.Running)
        {
            Cancel = true;
            // Give thread a chance to stop
            processThread.Join(500);
            processThread.Abort();
        }
    }

    void timer_Tick(object sender, EventArgs e)
    {
        processThread = new System.Threading.Thread(new ThreadStart(DoWork));
        processThread.Start();
    }

    private void DoWork()
    {
        try
        {
            while (!Cancel)
            {

            if (Cancel) { return; }
            // Do General Work

            System.Threading.Thread.BeginCriticalRegion();
            {
                // Do work that should not be aborted in here.
            }
            System.Threading.Thread.EndCriticalRegion();
            }

        }
        catch (System.Threading.ThreadAbortException tae)
        {
            // Clean up correctly to leave program in stable state.
        }
    }
}

Ответ 5

Использовать подход, основанный на подходе System.Threading.WaitHandle.

using System.Threading;
private Thread _thread;
private ManualResetEvent _shutdownEvent = new ManualResetEvent(false);
private ManualResetEvent _scheduleEvent = new ManualResetEvent(false);
private System.Timers.Timer _scheduleTimer = new System.Timers.Timer();
protected override void OnStart(string[] args)
{
    // Configure the timer.
    _scheduleTimer.AutoReset = false;
    _scheduleTimer.Interval = 120000; // 2 minutes in milliseconds
    _scheduleTimer.Elapsed += delegate { _scheduleEvent.Set(); }

    // Create the thread using anonymous method.
    _thread = new Thread( delegate() {
        // Create the WaitHandle array.
        WaitHandler[] handles = new WaitHandle[] {
            _shutdownEvent,
            _scheduleEvent
        };
        // Start the timer.
        _scheduleTimer.Start();
        // Wait for one of the events to occur.
        while (!_shutdownEvent.WaitOne(0)) {
            switch (WaitHandle.WaitAny(handles)) { 
               case 0:  // Shutdown Event
                   break;
               case 1:  // Schedule Event
                   _scheduleTimer.Stop();
                   _scheduleEvent.Reset();
                   ThreadPool.QueueUserWorkItem(PerformScheduledWork, null);
                   break;
               default:
                   _shutdownEvent.Set(); // should never occur
            }
        }
    } );
    _thread.IsBackground = true;
    _thread.Start();
}
protected override void OnStop()
{
    // Signal the thread to shutdown.
    _shutdownEvent.Set();
    // Give the thread 3 seconds to terminate.
    if (!_thread.Join(3000)) {
        _thread.Abort(); // not perferred, but the service is closing anyway
    }
}
private void PerformScheduledWork(object state)
{
    // Perform your work here, but be mindful of the _shutdownEvent in case
    // the service is shutting down.
    //
    // Reschedule the work to be performed.
     _scheduleTimer.Start();
}

Ответ 6

Вы действительно не хотите использовать фона рабочего. Фоновые работники используются, когда у вас что-то происходит на переднем плане (например, пользовательский интерфейс), и вы также хотите, чтобы что-то еще делалось на фоне. В вашем случае нет обработки переднего плана, все, что у вас есть, - это одно задание, которое нужно запускать каждый раз через некоторое время.

Кроме того, не беспокойтесь о спящем бизнесе и т.д. Вместо этого используйте фреймворк планировщика, например Quartz.NET, чтобы разбудить его время от времени. Таким образом, когда ваш сервис запускается, он инициализирует планировщик и ничего не делает до тех пор, пока планировщик не проснется. Когда планировщик просыпается, он вызывается методом объекта, который вы указываете ему, когда вы его инициализируете.

Таким образом, служба будет потреблять любой процессор только на холостом ходу и работать при необходимости.

Ответ 8

У кого-то был похожий вопрос на Суперпользователя. Вы можете установить инструмент, который контролирует службы Windows. Что-то вроде Service Hawk поможет вам сохранить запуск сервисов или позволить вам запланировать автоматические перезагрузки (возможно, в течение ночи), чтобы поддерживать работу плавно.

Ответ 9

В моей компании мы полагаемся на планировщик задач Windows, чтобы инициировать службу, а затем отключить сервис. Это гарантирует, что наш сервис всегда запускается в нужное время, и система планирования позволит сообщать об успехе/неудаче и т.д.

Ответ 10

Используйте таймер для этого.

Ответ 11

У меня было такое же обсуждение с коллегами около 1 часа назад! Я пошел с опцией while (_isPolling), потому что мне нужно, чтобы работа происходила синхронно. Я не хотел, чтобы одна и та же работа была подхвачена другой нитью (подход Timer), и реализация дополнительной блокировки для этого казалась пустой тратой.

Ответ 12

Я применил комбинацию таймера и рабочего потока, и пока это работает нормально.

Я устанавливаю свой таймер на галочку каждую минуту, и, если время соответствует графику, я создаю рабочий поток.

Я использовал эту технику при выполнении домашнего хозяйства:

if (nowTimeVar.ToShortTimeString().CompareTo(houseKeep.ToShortTimeString()) == 0)
{
    myHouseKeeper = new clsHouseKeep(archiveFolder, lastday, myCounter, myLogger);                
}    

Ответ 13

После проверки партии учебника я разработал сервис Windows, который периодически запускается каждые 60 минут, и он начнет процесс в фоновом режиме и запустит Test.exe.

public partial class Scheduler : ServiceBase
{
    private Timer timer1 = null;


    public Scheduler()
    {
        InitializeComponent();
    }
    // Get the Exe path
    private string GetPath()
    {
        Assembly assembly = Assembly.GetExecutingAssembly();
        return Path.Combine(Path.GetDirectoryName(assembly.Location), "Test.exe");

    }
    // you can right your own custom code
    // Above vista version the process works as Administrator- "runas" and in old OS it will Start process as per Administartor rights  
    public void startprocess()
    {
       // System.Diagnostics.Process.Start(GetPath());
        System.Diagnostics.Process process = null;
        System.Diagnostics.ProcessStartInfo processStartInfo;

        processStartInfo = new System.Diagnostics.ProcessStartInfo();

        processStartInfo.FileName = GetPath();

        if (System.Environment.OSVersion.Version.Major >= 6)  // Windows Vista or higher
        {
            processStartInfo.Verb = "runas";
        }
        else
        {
            // No need to prompt to run as admin
        }

        processStartInfo.Arguments = "";

        process = System.Diagnostics.Process.Start(processStartInfo);

    }
    // On start method will load when system Start 
    // timer1_tick Event will call every hour after once start the service automatically
    protected override void OnStart(string[] args)
    {
        //System.Diagnostics.Debugger.Launch();
        timer1 = new Timer();
        this.timer1.Interval = 3600000; //every 60 min
        this.timer1.Elapsed += new System.Timers.ElapsedEventHandler(this.timer1_Tick);
        timer1.Enabled = true;

    }

    // Timer1_tick will Start process every hour
    private void timer1_Tick(object sender, ElapsedEventArgs e)
    {
        //Write code here to do some job depends on your requirement
        startprocess();
    }
    // Method will stop the service
    // we have set the method stop service as false. so service will not stop and run every hour 
    protected override void OnStop()
    {
        timer1.Enabled = false;

    }

}