我有一个Windows服务,它有一个计时器从配置中读取间隔。
DipRedipServiceTimer_Elapsed事件在首次运行服务时 1000 毫秒后调用。在运行此计时器的下一个循环之前,必须执行用此方法编写的代码。但是,即使第一个周期尚未完成,我也看到DipRedipServiceTimer_Elapsed事件触发。这结果是两个线程在同一段代码上工作,以及一些非常可怕的问题。我怎样才能防止这种情况发生?请指教。
partial class DIPREDIPServiceHost : ServiceBase
{
#region Private Fields
/// <summary>
/// Timer for polling job pool on timely basis
/// </summary>
private Timer DipRedipServiceTimer;
#endregion
public DIPREDIPServiceHost()
{
InitializeComponent();
}
protected override void OnStart(string[] args)
{
DipRedipServiceTimer = new Timer();
DipRedipServiceTimer.Enabled = true;
DipRedipServiceTimer.Interval = 1000;
DipRedipServiceTimer.AutoReset = false;
DipRedipServiceTimer.Elapsed += new ElapsedEventHandler(DipRedipServiceTimer_Elapsed);
}
protected override void OnStop()
{
if (DipRedipServiceTimer != null)
{
DipRedipServiceTimer.Enabled = false;
DipRedipServiceTimer.Stop();
DipRedipServiceTimer = null;
}
}
#region "Timer Elapsed Event"
/// <summary>
/// Handles the Elapsed event of the timer control.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">The <see cref="System.Timers.ElapsedEventArgs"/> instance containing the event data.</param>
void DipRedipServiceTimer_Elapsed(object sender, ElapsedEventArgs e)
{
//disable timers as at a given time only one thread should process dip/redip.
DipRedipServiceTimer.Stop();
DipRedipServiceTimer.AutoReset = false;
DipRedipServiceTimer.Enabled = false;
try
{
IDipRedipController controller = new DipRedipController();
try
{
DipRedipConfiguration config = controller.GetDipRedipConfiguration();
// In case configuration has been retrieved, set timer defined.
if (config != null)
{
//set timer interval after reading from config file.
DipRedipServiceTimer.Interval = config.FileGenerationInterval * 60000;
controller.dipRedipConfiguration = config;
LoggingHelper.LogMessage(String.Format("Dip Service timer initialized at {0}", DateTime.UtcNow), Source.EDiscDIPREDIPService, LogCategory.Exception);
//Process Dip
bool dipSuccess = controller.ProcessDIP();
//Process Re-Dip
bool redipSuccess = controller.ProcessREDIP();
//Enable timers for next cycle
LoggingHelper.LogMessage(String.Format("Dip Service timer completed at {0}", DateTime.UtcNow), Source.EDiscDIPREDIPService, LogCategory.Exception);
}
// In case configuration is null, get the default timer defined in App.Config file.
else
{
int interval = 0;
int.TryParse(ConfigurationManager.AppSettings.Get("DefaultTimerValue"), out interval);
DipRedipServiceTimer.Interval = interval * 60000;
LoggingHelper.LogWarning("Configuration for Dip/Redip could not be fetched from database.", Source.FileImportService, LogCategory.Exception);
}
DipRedipServiceTimer.Enabled = true;
DipRedipServiceTimer.Start();
}
catch (FaultException ex)
{
LoggingHelper.LogException("Exception Occured in DipRedipServiceTimer_Elapsed method of Dip/Redip Window Service", ex, Source.EDiscDIPREDIPService);
}
}
catch (Exception ex)
{
LoggingHelper.LogException("Exception Occured in the DipRedip Service Host Window Service", ex, Source.EDiscDIPREDIPService);
}
}
#endregion
}
以下链接http://msdn.microsoft.com/en-us/library/system.timers.timer.interval.aspx
描述再次设置间隔的行为。在进行任何处理之前,我正在设置配置间隔,从而导致计时器重置并根据文档取消事件。
修复:- 处理完成后我正在设置间隔。这将重置计时器,经过的事件将在配置的间隔后触发。也不再需要以下代码行
DipRedipServiceTimer.Stop();
DipRedipServiceTimer.AutoReset = false;
DipRedipServiceTimer.Enabled = false;
因为在初始化计时器时自动重置设置为 false。
#region "Timer Elapsed Event"
/// <summary>
/// Handles the Elapsed event of the timer control.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">The <see cref="System.Timers.ElapsedEventArgs"/> instance containing the event data.</param>
void DipRedipServiceTimer_Elapsed(object sender, ElapsedEventArgs e)
{
try
{
IDipRedipController controller = new DipRedipController();
try
{
DipRedipConfiguration config = controller.GetDipRedipConfiguration();
if (config != null)
{
//set timer interval after reading from config file.
controller.dipRedipConfiguration = config;
LoggingHelper.LogMessage(String.Format("Dip Service timer initialized at {0}", DateTime.UtcNow), Source.EDiscDIPREDIPService, LogCategory.Exception);
//Process Dip
bool dipSuccess = controller.ProcessDIP();
//Process Re-Dip
bool redipSuccess = controller.ProcessREDIP();
// In case configuration has been retrieved, set timer defined.
DipRedipServiceTimer.Interval = config.FileGenerationInterval * 60000;
//Enable timers for next cycle
LoggingHelper.LogMessage(String.Format("Dip Service timer completed at {0}", DateTime.UtcNow), Source.EDiscDIPREDIPService, LogCategory.Exception);
}
// In case configuration is null, get the default timer defined in App.Config file.
else
{
int interval = 0;
int.TryParse(ConfigurationManager.AppSettings.Get("DefaultTimerValue"), out interval);
DipRedipServiceTimer.Interval = interval * 60000;
LoggingHelper.LogWarning("Configuration for Dip/Redip could not be fetched from database.", Source.EDiscDIPREDIPService, LogCategory.Exception);
}
DipRedipServiceTimer.Start();
}
catch (Exception ex)
{
LoggingHelper.LogException("Exception Occured in DipRedipServiceTimer_Elapsed method of Dip/Redip Window Service", ex, Source.EDiscDIPREDIPService);
}
}
catch (Exception ex)
{
LoggingHelper.LogException("Exception Occured in the DipRedip Service Host Window Service", ex, Source.EDiscDIPREDIPService);
}
}
#endregion