C# 带计时器的 Windows 服务

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/12885013/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-10 00:49:15  来源:igfitidea点击:

Windows service with timer

c#.netwindowstimerwindows-services

提问by Nitin Kabra

I have created a windows service with timer in c#.net. it works fine while i debug/build the project in visual studio but it does not perform its operation after installation.

我在 c#.net 中创建了一个带有计时器的 Windows 服务。当我在 Visual Studio 中调试/构建项目时它工作正常,但安装后它不执行其操作。

What might be the reason behind this ?

这背后的原因可能是什么?

code :

代码 :

public partial class Service1 : ServiceBase
{
        FileStream fs;
        StreamWriter m_streamWriter;
        Timer tm = new Timer();

        public Service1()
        {
            InitializeComponent();

            this.ServiceName = "timerservice";

            tm.Interval = 2000;
            tm.Tick += new EventHandler(PerformOperations);
            tm.Start();

            fs = new FileStream(@"c:\mcWindowsService.txt", FileMode.OpenOrCreate, FileAccess.Write);

            m_streamWriter = new StreamWriter(fs);
            m_streamWriter.BaseStream.Seek(0, SeekOrigin.End);
        }

        private void PerformOperations(object sener, EventArgs e)
        {
            //StreamWriter swr = new StreamWriter("c:\test_from_database.txt",true);

            try
            {
                OdbcConnection con = new OdbcConnection("DSN=liquor_data");

                OdbcDataAdapter adp = new OdbcDataAdapter("", con);

                DataSet ds = new DataSet();

                string sql = "select * from item_group";
                adp.SelectCommand.CommandText = sql;

                adp.Fill(ds, "item_group");

                foreach (DataRow dr in ds.Tables["item_group"].Rows)
                {
                    //      swr.Write(dr["group_name"].ToString() + "\t\t" + DateTime.Now.TimeOfDay.ToString() + "\n");

                    //Console.WriteLine(dr["group_name"].ToString() + "\t\t" + DateTime.Now.TimeOfDay.ToString() + "\n");
                    m_streamWriter.WriteLine(dr["group_name"].ToString() + "\t\t" + DateTime.Now.TimeOfDay.ToString() + "\n");
                }

                m_streamWriter.Flush();
            }

            catch (Exception ex)
            {
                // swr.Write("Error :"+ ex.Message + "\t\t" + DateTime.Now.TimeOfDay.ToString() + "\n"); }
            }
        }
    }

采纳答案by T-moty

First approach with Windows Service is not easy..

Windows 服务的第一种方法并不容易..

A long time ago, I wrote a C# service.

很久以前,我写了一个 C# 服务。

This is the logic of the Service class (tested, works fine):

这是 Service 类的逻辑(经过测试,工作正常):

namespace MyServiceApp
{
    public class MyService : ServiceBase
    {
        private System.Timers.Timer timer;

        protected override void OnStart(string[] args)
        {
            this.timer = new System.Timers.Timer(30000D);  // 30000 milliseconds = 30 seconds
            this.timer.AutoReset = true;
            this.timer.Elapsed += new System.Timers.ElapsedEventHandler(this.timer_Elapsed);
            this.timer.Start();
        }

        protected override void OnStop()
        {
            this.timer.Stop();
            this.timer = null;
        }

        private void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            MyServiceApp.ServiceWork.Main(); // my separate static method for do work
        }

        public MyService()
        {
            this.ServiceName = "MyService";
        }

        // service entry point
        static void Main()
        {
            System.ServiceProcess.ServiceBase.Run(new MyService());
        }
    }
}

I recommend you write your real service work in a separate static method (why not, in a console application...just add reference to it), to simplify debugging and clean service code.

我建议您在单独的静态方法中编写真正的服务工作(为什么不在控制台应用程序中...只需添加对它的引用),以简化调试和清理服务代码。

Make sure the interval is enough, and write in log ONLY in OnStart and OnStop overrides.

确保间隔足够,并仅在 OnStart 和 OnStop 覆盖中写入日志。

Hope this helps!

希望这可以帮助!

回答by Luis Quijada

You need to put your main code on the OnStartmethod.

您需要将主要代码放在OnStart方法上。

This other SO answerof mine might help.

我的另一个SO 答案可能会有所帮助。

You will need to put some code to enable debugging within visual-studio while maintaining your application valid as a windows-service. This other SO threadcover the issue of debugging a windows-service.

您将需要放置一些代码以在视觉工作室中启用调试,同时保持您的应用程序作为 Windows 服务有效。另一个SO 线程涵盖了调试 Windows 服务的问题。

EDIT:

编辑

Please see also the documentation available herefor the OnStartmethod at the MSDN where one can read this:

另请参阅此处提供的文档OnStart以了解 MSDN 上的方法,您可以在其中阅读:

Do not use the constructor to perform processing that should be in OnStart. Use OnStartto handle all initialization of your service. The constructor is called when the application's executable runs, not when the service runs. The executable runs before OnStart. When you continue, for example, the constructor is not called again because the SCM already holds the object in memory. If OnStopreleases resources allocated in the constructor rather than in OnStart, the needed resources would not be created again the second time the service is called.

不要使用构造函数来执行应该在 OnStart 中的处理。使用OnStart处理服务的所有初始化。构造函数在应用程序的可执行文件运行时调用,而不是在服务运行时调用。可执行文件在OnStart之前运行。例如,当您继续时,不会再次调用构造函数,因为 SCM 已将对象保存在内存中。如果OnStop释放在构造函数中而不是在OnStart 中分配的资源,则第二次调用服务时将不会再次创建所需的资源。

回答by Uwe K?hler

Here's a working example in which the execution of the service is started in the OnTimedEvent of the Timer which is implemented as delegate in the ServiceBase class and the Timer logic is encapsulated in a method called SetupProcessingTimer():

这是一个工作示例,其中服务的执行在 Timer 的 OnTimedEvent 中启动,该定时器在 ServiceBase 类中作为委托实现,并且 Timer 逻辑封装在一个名为 SetupProcessingTimer() 的方法中:

public partial class MyServiceProject: ServiceBase
{

private Timer _timer;

public MyServiceProject()
{
    InitializeComponent();
}

private void SetupProcessingTimer()
{
    _timer = new Timer();
    _timer.AutoReset = true;
    double interval = Settings.Default.Interval;
    _timer.Interval = interval * 60000;
    _timer.Enabled = true;
    _timer.Elapsed += new ElapsedEventHandler(OnTimedEvent);
}

private void OnTimedEvent(object source, ElapsedEventArgs e)
{
    // begin your service work
    MakeSomething();
}

protected override void OnStart(string[] args)
{
    SetupProcessingTimer();
}

...
}

The Interval is defined in app.config in minutes:

间隔在 app.config 中以分钟为单位定义:

<userSettings>
    <MyProject.Properties.Settings>
        <setting name="Interval" serializeAs="String">
            <value>1</value>
        </setting>
    </MyProject.Properties.Settings>
</userSettings>