简体   繁体   English

如何使进程始终运行并在特定时间执行功能

[英]How to make a process running always and execute a function at specific time

I want to make a process/system that should be in a running state constantly and execute a specific function at a specific time period. 我想使一个流程/系统应该一直处于运行状态,并在特定时间段执行特定功能。

For example, if I want the system to send an email to a specific address every week then what should I do? 例如,如果我希望系统每周发送一封电子邮件到特定地址,那我该怎么办?

Running always: go for Windows service For periodic things: go for timers 始终运行:用于Windows服务对于定期的事情:用于计时器

So have a Windows service which maintains a timer set to trigger at the required interval and do whatever you need there. 因此,有一个Windows服务,该服务维护一个计时器,该计时器设置为按所需的时间间隔触发,并在那里执行所需的任何操作。

You can use open-source Quartz.NET scheduler( http://www.quartz-scheduler.net/ ), which can trigger your jobs at specified times and intervals. 您可以使用开源的Quartz.NET调度程序( http://www.quartz-scheduler.net/ ),该调度程序可以在指定的时间和间隔触发您的作业。 My suggestion is to host the scheduler job in Windows service. 我的建议是将调度程序作业托管在Windows服务中。

Here is my example, for some tasks it's ok. 这是我的示例,对于某些任务来说还可以。

public class Timer : IRegisteredObject
{
    private Timer _timer;
    public static void Start()
    {
        HostingEnvironment.RegisterObject(new Timer());
    }

    public Timer()
    {
        StartTimer();
    }

    private void StartTimer()
    {
        _timer = new Timer(BroadcastUptimeToClients, null, TimeSpan.FromSeconds(0), TimeSpan.FromMilliseconds(100));     
    }
    private void BroadcastUptimeToClients(object state)
    {
        //some action
    }

    public void Stop(bool immediate)
    {
        //throw new System.NotImplementedException();
    }
}

In Global.asax 在Global.asax中

   Timer.Start();

In your case I will agree with @ Arsen Mkrtchyan - use OS scheduler. 在您的情况下,我将同意@ Arsen Mkrtchyan-使用OS调度程序。 If you would like to use windows service, here is how would look your service: 如果您想使用Windows服务,以下是您的服务外观:

partial class MyService
{
    /// <summary> 
    /// Required designer variable.
    /// </summary>
    private System.ComponentModel.IContainer components = null;

    private Timer _watcherTimer = new System.Timers.Timer();

    private static Logger logger = LogManager.GetCurrentClassLogger();
    /// <summary>
    /// Clean up any resources being used.
    /// </summary>
    /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
    protected override void Dispose(bool disposing)
    {
        if (disposing && (components != null))
        {
            components.Dispose();
        }
        base.Dispose(disposing);
    }

    #region Component Designer generated code

    /// <summary> 
    /// Required method for Designer support - do not modify 
    /// the contents of this method with the code editor.
    /// </summary>
    private void InitializeComponent()
    {
        components = new System.ComponentModel.Container();
        this.ServiceName = "MyService";

        this._watcherTimer.Interval = 6000;
        this._watcherTimer.Enabled = false;
        this._watcherTimer.Elapsed += new System.Timers.ElapsedEventHandler(this.Timer_Tick);
    }

    #endregion
}

partial class MyService : ServiceBase
{
    public MyService()
    {
        try
        {
            InitializeComponent();
        }
        catch (Exception e)
        {
            logger.Error("Error initializing service",e);
            Stop();
        }

    }

    protected override void OnStart(string[] args)
    {
        _watcherTimer.Enabled = true;
        logger.Info("Service has started at " + DateTime.UtcNow.ToLongDateString());
    }

    protected override void OnStop()
    {
        logger.Info("Service has stopped at " + DateTime.UtcNow.ToLongDateString());
    }

    private void Timer_Tick(object sender, ElapsedEventArgs e)
    {
        logger.Info("Timer Tick");
    }
}

Installer: 安装程序:

[RunInstaller(true)]
public class WindowsServiceInstaller : Installer
{
    /// <summary>
    /// Public Constructor for WindowsServiceInstaller.
    /// - Put all of your Initialization code here.
    /// </summary>
    public WindowsServiceInstaller()
    {
        var serviceProcessInstaller =
                           new ServiceProcessInstaller();
        var serviceInstaller = new ServiceInstaller();

        //# Service Account Information
        serviceProcessInstaller.Account = ServiceAccount.LocalSystem;
        serviceProcessInstaller.Username = null;
        serviceProcessInstaller.Password = null;

        //# Service Information
        serviceInstaller.DisplayName = "MY SERVICE DISPLAY NAME";
        serviceInstaller.Description = "MY SERVICE DESCRIPTION";
        serviceInstaller.StartType = ServiceStartMode.Automatic;

        //# This must be identical to the WindowsService.ServiceBase name
        //# set in the constructor of WindowsService.cs
        serviceInstaller.ServiceName = "MyService";

        Installers.Add(serviceProcessInstaller);
        Installers.Add(serviceInstaller);
    }
}

Run this with .bat 用.bat运行

static class Program
{
    static void Main(string[] args)
    {
        if (args.Length > 0)
        {
            //Install service
            if (args[0].Trim().ToLower() == "/i")
            { System.Configuration.Install.ManagedInstallerClass.InstallHelper(new[] { "/i", Assembly.GetExecutingAssembly().Location }); }

            //Uninstall service                 
            else if (args[0].Trim().ToLower() == "/u")
            { System.Configuration.Install.ManagedInstallerClass.InstallHelper(new[] { "/u", Assembly.GetExecutingAssembly().Location }); }
        }
        else
        {
            var servicesToRun = new ServiceBase[] { new MyService() };
            ServiceBase.Run(servicesToRun);
        }
    }
}

install.bat install.bat

    @ECHO OFF

    REM Prevent changing current directory when run bat file as administrator on win7

    @setlocal enableextensions
    @cd /d "%~dp0"

    REM The following directory is for .NET 4.0

    set DOTNETFX4=%SystemRoot%\Microsoft.NET\Framework\v4.0.30319
    set PATH=%PATH%;%DOTNETFX4%

    echo Installing WindowsService...
    echo  "%CD%\WindowsService\Service\bin\Debug\Service.exe"
    echo ---------------------------------------------------
    InstallUtil /i "%CD%\WindowsService\Service\bin\Debug\Service.exe"
    echo ---------------------------------------------------
    echo Done.
    set /p DUMMY=Hit ENTER to continue...

unistall.bat unistall.bat

     @ECHO OFF

     REM Prevent changing current directory when run bat file as administrator on win7

     @setlocal enableextensions
     @cd /d "%~dp0"

     REM The following directory is for .NET 4.0

     set DOTNETFX4=%SystemRoot%\Microsoft.NET\Framework\v4.0.30319
     set PATH=%PATH%;%DOTNETFX4%

     echo Installing WindowsService...
     echo ---------------------------------------------------
     InstallUtil /u "%CD%\WindowsService\Service\bin\Debug\Service.exe"
     echo ---------------------------------------------------
     echo Done.
     set /p DUMMY=Hit ENTER to continue...

my folder hierarchy: 我的文件夹层次结构:

    install.bat
    uninstall.bat
    service-project-folder
       packages
       project-folder
       .sln file

By making use of ReactiveExtensions you could use the following code if you were interested in doing something as simple as printing to the console as in your currently on hold question here https://stackoverflow.com/questions/30473281/how-to-print-a-string-in-c-sharp-after-every-1-minute-using-timer . 通过使用ReactiveExtensions,如果您有兴趣像在当前保留的问题中打印到控制台一样简单,可以使用以下代码https://stackoverflow.com/questions/30473281/how-to-print每使用计时器1分钟后,C弦就会变尖 You can add Reactive Extensions by adding Rx-Main via NuGet. 您可以通过NuGet添加Rx-Main来添加Reactive Extensions。

using System;
using System.Reactive.Linq;

namespace ConsoleApplicationExample
{
    class Program
    {
        static void Main()
        {
            Observable.Interval(TimeSpan.FromMinutes(1))
            .Subscribe(_ =>
            {                   
                Console.WriteLine(DateTime.Now.ToString());
            });
            Console.WriteLine(DateTime.Now.ToString()); 
            Console.ReadLine();
        }
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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