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

本文关键字:定时间 执行 函数 运行 何使 进程 | 更新日期: 2023-09-27 17:50:35

我想做一个进程/系统,它应该一直处于运行状态,并在特定的时间段执行特定的功能。

例如,如果我想让系统每周发送一封电子邮件到一个特定的地址,那么我应该怎么做?

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

Running always: go for Windows service对于周期性的东西:使用计时器

所以有一个Windows服务,它维护一个定时器设置在所需的间隔触发,做任何你需要在那里。

你可以使用开源的Quartz。. NET调度器(http://www.quartz-scheduler.net/),它可以在指定的时间和间隔触发作业。我的建议是在Windows服务中托管调度程序作业。

这是我的例子,对于一些任务它是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();
    }
}
在Global.asax

   Timer.Start();

在你的情况下,我同意@ Arsen Mkrtchyan -使用操作系统调度程序。如果你想使用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");
    }
}

安装程序:

[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);
    }
}

用.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

    @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

     @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...

我的文件夹层次:

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

通过使用ReactiveExtensions,您可以使用以下代码,如果您有兴趣做一些像打印到控制台一样简单的事情,就像您目前在这里的hold问题https://stackoverflow.com/questions/30473281/how-to-print-a-string-in-c-sharp-after-every-1-minute-using-timer。你可以通过NuGet添加Rx-Main来添加响应式扩展。

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();
        }
    }
}