我最近从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来检查配置文件中的时间然后运行我的代码。任何帮助表示赞赏
答案 0 :(得分:1)
转储定时器,启动线程,使用Sleep(30000)循环。
编辑:更好的是,获取RTC值并计算在下一个运行时间之前剩余的ms数。该间隔除以2和Sleep()。继续这样做,直到间隔小于100ms,然后运行函数,Sleep()另外1000,(以确保RTC时间现在晚于RTC时间读取配置文件),并循环。
答案 1 :(得分:1)
你为什么要轮询时间?尽管每30秒进行一次轮询,但在严重负载/ ThreadPool饥饿情况下,可能(尽管极不可能)定时器不会在所需的分钟插槽中触发。
为什么不在到期时间之前找出TimeSpan并将计时器设置为当时触发?
目前尚不清楚您正在使用哪个计时器,但除了System.Threading.Timer之外,我不会使用Windows服务以外的任何计时器。
答案 2 :(得分: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)。谢谢大家的帮助