带计时器的 Windows 服务
Posted
技术标签:
【中文标题】带计时器的 Windows 服务【英文标题】:Windows service with timer 【发布时间】:2012-10-04 19:12:54 【问题描述】:我在 c#.net 中创建了一个带有计时器的 Windows 服务。当我在 Visual Studio 中调试/构建项目时它工作正常,但安装后它不执行操作。
这背后的原因可能是什么?
代码:
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");
【问题讨论】:
账号安装后是否有权限运行windows服务? 尝试取消注释 catch 以查看是否抛出了一些错误。还要检查 Windows 事件日志是否有任何错误。 很难相信这适用于您的开发机器。您正在使用的 Timer 类需要一个消息循环。请改用 System.Threading.Timer。 如果你想确保事件不会被非后台线程欺负,或者悄悄地丢失(计时器在历史上一直存在在 win svc 中永远丢失事件的问题),你不能完全使用计时器。 【参考方案1】:Windows 服务的第一种方法并不容易..
很久以前,我写了一个C#服务。
这是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());
我建议您在单独的静态方法中编写您的真实服务工作(为什么不,在控制台应用程序中......只需添加对它的引用),以简化调试和清理服务代码。
确保间隔足够,并且只在 OnStart 和 OnStop 覆盖中写入日志。
希望这会有所帮助!
【讨论】:
"并且只在 OnStart 和 OnStop 覆盖中写入日志。"为什么?您不能在每个计时器经过的事件中写入文本文件吗?我遇到了这个问题......我有自己的函数可以写入文本文件(日志),但它不起作用(仅适用于启动和停止),你能帮我理解问题所在吗? 是的,你也可以写入timer_tick方法,但是对我来说是不必要的(主要工作方法必须写入它的日志)。你能告诉我更多(例外等)吗? 绝对运作良好。按照时间间隔继续工作。谢谢!【参考方案2】:您需要将主代码放在OnStart
方法上。
我的另一个SO answer 可能会有所帮助。
您需要添加一些代码以在visual-studio 中启用调试,同时保持您的应用程序作为Windows 服务有效。另一个SO thread 涵盖了调试 Windows 服务的问题。
编辑:
另请参阅 here 的可用文档,了解 MSDN 上的 OnStart
方法,您可以在其中阅读:
不要使用构造函数来执行应该在 开机。使用 OnStart 处理服务的所有初始化。这 构造函数在应用程序的可执行文件运行时调用,而不是在 服务运行。可执行文件在 OnStart 之前运行。当你 继续,例如,构造函数不会再次调用,因为 SCM 已经将对象保存在内存中。如果 OnStop 释放资源 在构造函数中而不是在 OnStart 中分配,需要 第二次服务时不会再次创建资源 调用。
【讨论】:
【参考方案3】:这是一个工作示例,其中服务的执行是在 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();
...
间隔在 app.config 中以分钟为单位定义:
<userSettings>
<MyProject.Properties.Settings>
<setting name="Interval" serializeAs="String">
<value>1</value>
</setting>
</MyProject.Properties.Settings>
</userSettings>
【讨论】:
以上是关于带计时器的 Windows 服务的主要内容,如果未能解决你的问题,请参考以下文章
如何知道是不是从 Windows 本地服务启用了唤醒计时器?