2012-09-20 77 views
0

我最近从vb.net转移到C#和我有开创我已创建的Windows服务的问题。我希望该服务在我的app.config文件中每天读取一次。在vb.net我用了一个定时器,并呼吁方法:在设定时间启动Windows服务

Private WithEvents Alarm As Timer = New Timer(30000) 
Public Sub OnTimedEvent(ByVal source As Object, ByVal e As ElapsedEventArgs) Handles Alarm.Elapsed 

继承人的C#代码,我到目前为止有:

namespace MyWindowsService 
{ 
class Program : ServiceBase 
{ 
    Timer alarm = new Timer(30000); 
    public string str_dbserver; 
    public string str_year; 
    public string str_time; 
    public string str_dbConnection; 
    bool service_running; 

static void Main(string[] args) 
{ 
    ServiceBase.Run(new Program()); 
} 

public Program() 
{ 
    this.ServiceName = "MyWindowsService"; 
} 


public void OnTimedEvent(object source, ElapsedEventArgs e) 
{  
    service_running = false; 

    //declare variables and get info from config file 
    DateTime dtNow; 
    dtNow = DateTime.Now; 
    System.Configuration.AppSettingsReader configurationAppSettings = new System.Configuration.AppSettingsReader(); 
    str_dbserver = Convert.ToString(configurationAppSettings.GetValue("dbServer", typeof(System.String))); 
    str_year = Convert.ToString(configurationAppSettings.GetValue("sYear", typeof(System.String))); 
    str_time = Convert.ToString(configurationAppSettings.GetValue("stime", typeof(System.String))); 

    //split time from config to get hour, minute, second 
    string[] str_atime = str_time.Split(new string[] { ":" }, StringSplitOptions.None); 

    //check that service is not currently running and time matches config file 
    if (DateTime.Now.Hour == Convert.ToInt32(str_atime[0]) && DateTime.Now.Minute == Convert.ToInt32(str_atime[1]) && service_running == false) 
    { 
     //service now running so write to log and send email notification 
     service_running = true; 

     try 
     { 
      //call functions containing service code here 
      Function1(); 
      Function2(); 
     } 
     catch (Exception ex) 
     { 

     } //end try/catch 

     //service now finished, sleep for 60 seconds 
     service_running = false; 
    } //end if 
} //end OnTimedEvent 

我需要我的代码来调用OnTimedEvent每30秒检查时间从配置文件,然后运行我的代码。任何帮助赞赏

+1

你在哪里启动计时器?我在任何地方都看不到。 – Oded

+0

我在服务代码的OnStart中这样做:protected override void OnStart(string [] args) { base.OnStart(args); // TODO:将您的起始代码放在这里 alarm.Enabled = true; alarm.Start(); } // end onStart –

+0

我编辑了你的标题。请参阅:“[应该在其标题中包含”标签“](http://meta.stackexchange.com/questions/19190/)”,其中的共识是“不,他们不应该”。 –

回答

1

转储计时器,启动线程,使用睡眠(30000)循环。

编辑:更好的是,获取RTC值并计算在下一次运行时间之前剩余的ms数。除以2和Sleep()间隔。继续这样做,直到间隔小于100ms,然后运行函数Sleep()再次运行1000次(以确保RTC时间现在晚于RTC每天读取的时间配置文件),并循环。

1

你为什么在投票时间?尽管每30秒轮询一次,在严重负载/ ThreadPool饥饿的情况下,可能(尽管极不可能)定时器不会在所需的分钟时隙中触发。

为什么不计算TimeSpan直到到期时间并设置计时器在那个时间点火?

你不清楚你正在使用哪个计时器,但我不会使用System.Threading.Timer以外的任何其他Windows服务。

+0

+1为'找出TimeSpan直到到期时间,并设置计时器在那个时候触发',虽然这个解决方案(和我的)不能很好地处理配置文件中的变化 - 编辑文件时间到较早的时间不会改变等待间隔,直到下一次计时器触发前一个间隔。 –

0

感谢'Oded'和'Martin James'指引我朝着正确的方向前进。我在解决方案中缺少的是这个。我有下面的代码添加到构造器类,以便它会认识到,计时器已经过去了:

//call onTimedEvent when timer reaches 60 seconds 
alarm.Elapsed += new ElapsedEventHandler(OnTimedEvent); 
// Set the Interval to 60 second. 
alarm.Interval = 60000; 

然后我用下面的导入KERNEL32 DLL:

using System.Runtime.InteropServices; 

//import kernel32 so application can use sleep method 
    [DllImport("kernel32.dll")] 
    static extern void Sleep(uint dwMilliseconds); 

通过导入此DLL我然后可以使用睡眠(60000)一旦我的代码完成执行。谢谢大家的帮助

+2

嗯。 'Thread.Sleep'有人吗? Interop做睡眠?疯狂的sh * t。 http://msdn.microsoft.com/en-us/library/d00bd51t%28v=vs.80%29.aspx – spender

+0

即时消息不是最有经验的程序员...什么是我在这里做什么错?即时通讯不使用线程在我的代码...但如果我使用system.threading并做一个thread.sleep(60000);这会对我做同样的事吗? –

+0

如果你在做什么对你有用,没问题。我只是让你知道Thread.Sleep已经存在于.net中。无需与Windows API进行互操作。 – spender