我使用CacheItemRemovedCallback模拟了一个基于此源的Windows服务:
Simulate a Windows Service using ASP.NET to run scheduled jobs
除了应用程序回收或重新启动后的第一次运行之外,一切都运行良好。
的Global.asax.cs
protected void Application_Start(object sender, EventArgs e)
{
RegisterCacheEntry();
}
private bool RegisterCacheEntry()
{
if (null != HttpContext.Current.Cache[DummyCacheItemKey]) return false;
int interval = Properties.Settings.Default.SchedulerInterval;
HttpContext.Current.Cache.Add(
DummyCacheItemKey, "StartingScheduler", null,
Cache.NoAbsoluteExpiration, TimeSpan.FromHours(interval),
CacheItemPriority.NotRemovable,
new CacheItemRemovedCallback(CacheItemRemovedCallback)
);
return true;
}
public void CacheItemRemovedCallback(string key, object value, CacheItemRemovedReason reason)
{
Scheduler.HitPage(Properties.Settings.Default.Dummy);
string dirScheduler = Properties.Settings.Default.Scheduler;
Scheduler.Manage(dirScheduler);
}
protected void Application_BeginRequest(object sender, EventArgs e)
{
if (HttpContext.Current.Request.Url.ToString() == Properties.Settings.Default.Dummy)
{
RegisterCacheEntry();
}
}
公共静态类调度程序
public static string _DirScheduler { get; set; }
public static void Manage(string dirScheduler)
{
_DirScheduler = dirScheduler;
string[] schedulesCfg = Directory.GetFiles(dirScheduler, "*.xml");
foreach (string scheduleCfg in schedulesCfg)
{
//scheduleData = Class to store the schedule data
ThreadPool.QueueUserWorkItem(o => FireAway(scheduleData));
}
}
private static void FireAway(Schedule schedule)
{
string month = DateTime.Now.Month.ToString();
if (month.Length == 1)
{
month = month.Insert(0, "0");
}
// Wait Handle to Manage Access to Log File
EventWaitHandle waitHandle = new EventWaitHandle(true, EventResetMode.AutoReset, "LogFile_Shared");
// Lock the log file
waitHandle.WaitOne();
WriteLog("path_to_log_file", schedule, "started");
// Release the lock on log file
waitHandle.Set();
// Ok until here !
string message = ScheduleScript.Launch(schedule);
// Code not executed from here (only after application end or recycle)
if (schedule.Repeat == "0")
{
waitHandle.WaitOne();
UpdateScheduler(schedule);
waitHandle.Set();
}
// Lock the log file
waitHandle.WaitOne();
WriteLog("path_to_log_file", schedule, message);
// Release the lock on log file
waitHandle.Set();
}
private static void UpdateScheduler(Schedule schedule)
{
// Update a xml file containing scheduler data
}
公共静态类ScheduleScript
public static string Launch(Schedule schedule)
{
string message = "finished";
string messageScheduler = string.Empty;
using (WebClientCustom web = new WebClientCustom(10800000)) // 3 hours timeout
{
try
{
string res = web.DownloadString(schedule.Script);
}
catch (Exception e)
{
message = e.Message;
}
}
return message;
}
在静态类Scheduler中,所有内容都会执行到ScheduleScript.Launch(schedule)
。然后,代码不会执行(日志不会更新,状态已完成,并且调度程序xml未使用UpdateScheduler
方法更新)。
我尝试了一切,但没有成功。只有在应用程序被回收后才开始计划,才会出现这种情况。
例如,如果我的计划预计在上午10点启动并且尚未执行,并且我发布了新版本的应用程序或在计划的同一小时(上午10点)手动执行应用程序池回收,则会发生此行为