0

我最近从 vb.net 迁移到 C#,但在启动我创建的 Windows 服务时遇到问题。我希望每天从我的 app.config 文件中读取该服务。在 vb.net 中,我使用了一个 Timer 并调用了一个方法:

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

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

4

3 回答 3

1

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

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

于 2012-09-20T10:17:53.353 回答
1

你为什么要轮询时间?尽管每 30 秒轮询一次,但在严重的负载/线程池不足的情况下,定时器有可能(尽管极不可能)不会在所需的分钟槽内触发。

为什么不弄清楚 TimeSpan 直到到期时间并将计时器设置为在那个时候触发?

目前尚不清楚您使用的是哪个计时器,但我不会将 System.Threading.Timer 以外的任何东西用于 Windows 服务。

于 2012-09-20T10:20:52.380 回答
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,我可以在我的代码完成执行后使用 Sleep(60000)。感谢大家的帮助

于 2012-09-20T10:44:13.917 回答