使用定期任务在 C# 中构建 Windows 服务 [重复]

Posted

技术标签:

【中文标题】使用定期任务在 C# 中构建 Windows 服务 [重复]【英文标题】:Building Windows Service in C# with periodic task [duplicate] 【发布时间】:2021-02-08 13:50:30 【问题描述】:

我想用 C# 构建一个 Windows 服务。

此服务需要每隔 10 秒定期运行一次。

问题:

    Timers.timer 和 Threading.timer 有什么区别?

    如何调用带参数的 CheckingThings?

    如果我运行此代码,它会像此处声明的那样每秒多次调用 CheckingThings:

_timer = new Timer(new TimerCallback(CheckingThings), autoEvent, 5000, 1000);

这是我目前得到的:

public partial class WindowsService1 : ServiceBase


    // Logging
    private static Serilog.Core.Logger _logEvent;


    public WindowsService1()
    
        InitializeComponent();
    

    public void OnDebug() 
        OnStart(null);
    


    protected override void OnStart(string[] args)
    

        //Logging
        try 
            _logEvent = new LoggerConfiguration()
                .WriteTo.File(AppDomain.CurrentDomain.BaseDirectory + @"Logs\Logfile.txt", rollingInterval: RollingInterval.Month)
                .CreateLogger();
        
        catch (Exception e)
        
            _logEvent.Error("The logging service is not working as expected: errorMsg", e);
        

        try
        
        // initializing some data here

                var autoEvent = new AutoResetEvent(true);
                while (true)
                
                    _timer = new Timer(new TimerCallback(CheckingThings), autoEvent, 5000, 1000);
                
        
        catch (Exception e) 
            _logEvent.Error("An error occured while initializing service: 0", e);
        
    

    private static void CheckingThings(object stateInfo) 
        AutoResetEvent autoEvent = (AutoResetEvent)stateInfo;

    //These things needs to run periodically every 10s
    

    protected override void OnStop()
    
        _logEvent.Information("Stopping  Service ...");
    

【问题讨论】:

您的第一个问题已经在这里得到解答:***.com/questions/1416803/… 你似乎创建了无限数量的计时器while (true) _timer = new Timer(new TimerCallback(CheckingThings), autoEvent, 5000, 1000); 如果我删除 while 循环它只运行一次 您想构建 Windows 服务还是定期运行它 我如何使用参数调用 CheckingThings? - 如果您对计时器说“这里,每 10 秒调用一次此方法并提供各种参数”,您如何期待计时器知道要提供哪些参数?您如何期望手机的早上 8 点闹钟会打开您的咖啡机?您希望它如何拨入您上午 10 点会议的会议号码和 PIN 码? (提示;它不会 - 它只是提醒您当前时间,因此您必须执行这些操作) 【参考方案1】:

这是一个每分钟执行一些操作的服务类的框架,使用 System.Timers.Timer

public partial class XService : ServiceBase

    private Timer _minute = new Timer(60000);

    public XService()
    
        InitializeComponent();

        _minute.Elapsed += Minute_Elapsed;
    

    //this is async because my 'stuff' is async
    private async void Minute_Elapsed(object sender, ElapsedEventArgs e)
    
        _minute.Stop();
        try
        
            //stuff
        
        catch (Exception ex)
        
            //log ?
        
        finally
        
            _minute.Start();
        
    

    protected override void OnStart(string[] args)
    
        _minute.Start();            //this or..

        Minute_Elapsed(null, null); //..this, if you want to do the things as soon as the service starts (otherwise the first tick will be a minute after start is called
    

 ...

我通常会在我做我的事情时停止我的计时器 - 开始一项需要 10 分钟然后一分钟后再做一次的工作是没有意义的,因此停止/尝试/最终/开始模式

编辑:

这是课程的结尾部分,以及它是如何在调试(在 Visual Studio 内部)和发布(作为已安装的 Windows 服务)中启动/启动的:

        //just an adapter method so we can call OnStart like the service manager does, in a debugging context
        public void PubOnStop()
        
            OnStop();
        
    // end of XService class
        static void Main(string[] args)
        
#if DEBUG
            new XService().PubStart(args);
            Thread.Sleep(Timeout.Infinite);
#else

            ServiceBase[] ServicesToRun;
            ServicesToRun = new ServiceBase[]
            
                new XService()
            ;
            ServiceBase.Run(ServicesToRun);
#endif
        

【讨论】:

非常感谢!!!如果我必须从 text/ini 文件中读取要检查的内容怎么办?有可能通过那些吗? Minute_Elapsed 中的代码实际上没有任何限制。好吧,除非您以无权访问本地磁盘资源的用户身份运行该服务...阅读您的 INI如果您不想停止并重新启动获取新设置的服务 我试过你的骨架,但它没有做循环计时器?! 呃.. 我直接将它从一个工作服务中提取出来,该服务每分钟都会检查它必须编码的视频。你是如何开始服务的? 这就是我启动服务的方式 backgroundTask = Task.Factory.StartNew(() => CheckingThings(cancellation), canceling, TaskCreationOptions.LongRunning, TaskScheduler.Default);背景任务.Wait(); while (!cancellation.IsCancellationRequested) // 主线程需要在那里工作

以上是关于使用定期任务在 C# 中构建 Windows 服务 [重复]的主要内容,如果未能解决你的问题,请参考以下文章

如何在基于 C# 的 Windows 服务中处理以不同时间间隔并行运行的多个任务?

如何安排 C# Windows 服务每天执行任务?

定时任务-C#线程类 windows服务

C# 在高效的 Windows 服务中安排重复任务的最佳方法

一个 exe 中的多个 Windows 服务

在 iOS 相机中启动定期任务以使用帧数据的最佳方法是啥?