我在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"); }
}
}
}
答案 0 :(得分:55)
使用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覆盖中写入日志。
希望这有帮助!
答案 1 :(得分:7)
您需要将主代码放在OnStart
方法上。
我的另一个SO answer可能有所帮助。
您需要放置一些代码以在visual-studio中启用调试,同时保持您的应用程序作为Windows服务有效。另一个SO thread涵盖了调试Windows服务的问题。
修改强>:
请参阅MSDN上OnStart
方法的可用文档here,其中可以阅读此内容:
不要使用构造函数来执行应该处理的处理 的的OnStart 即可。使用 OnStart 处理服务的所有初始化。该 构造函数在应用程序的可执行文件运行时调用,而不是在何时运行 服务运行。可执行文件在 OnStart 之前运行。当你 继续,例如,因为没有再次调用构造函数 SCM已将对象保存在内存中。如果 OnStop 释放资源 在构造函数中而不是在 OnStart 中分配所需的 第二次服务时不会再创建资源 调用。
答案 2 :(得分:0)
这是一个工作示例,其中服务的执行是在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();
}
...
}
Interval在app.config中以分钟为单位定义:
<userSettings>
<MyProject.Properties.Settings>
<setting name="Interval" serializeAs="String">
<value>1</value>
</setting>
</MyProject.Properties.Settings>
</userSettings>