ฉันมีบริการที่เขียนด้วยภาษา C # (.NET 1.1) และต้องการให้ดำเนินการล้างข้อมูลตอนเที่ยงคืนของทุกคืน ฉันต้องเก็บรหัสทั้งหมดไว้ในบริการดังนั้นวิธีที่ง่ายที่สุดในการทำสิ่งนี้คืออะไร? ใช้Thread.Sleep()
และตรวจสอบเวลาที่หมุนไปหรือไม่?
ฉันมีบริการที่เขียนด้วยภาษา C # (.NET 1.1) และต้องการให้ดำเนินการล้างข้อมูลตอนเที่ยงคืนของทุกคืน ฉันต้องเก็บรหัสทั้งหมดไว้ในบริการดังนั้นวิธีที่ง่ายที่สุดในการทำสิ่งนี้คืออะไร? ใช้Thread.Sleep()
และตรวจสอบเวลาที่หมุนไปหรือไม่?
คำตอบ:
ฉันจะไม่ใช้ Thread.Sleep () ใช้งานที่กำหนดเวลาไว้ (ตามที่คนอื่นพูดถึง) หรือตั้งค่าตัวจับเวลาภายในบริการของคุณซึ่งจะเริ่มทำงานเป็นระยะ ๆ (เช่นทุกๆ 10 นาที) และตรวจสอบว่าวันที่เปลี่ยนแปลงไปหรือไม่ตั้งแต่การรันครั้งล่าสุด:
private Timer _timer;
private DateTime _lastRun = DateTime.Now.AddDays(-1);
protected override void OnStart(string[] args)
{
_timer = new Timer(10 * 60 * 1000); // every 10 minutes
_timer.Elapsed += new System.Timers.ElapsedEventHandler(timer_Elapsed);
_timer.Start();
//...
}
private void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
// ignore the time, just compare the date
if (_lastRun.Date < DateTime.Now.Date)
{
// stop the timer while we are running the cleanup task
_timer.Stop();
//
// do cleanup stuff
//
_lastRun = DateTime.Now;
_timer.Start();
}
}
ตรวจสอบQuartz.NET คุณสามารถใช้ได้ภายในบริการของ Windows ช่วยให้คุณสามารถเรียกใช้งานตามตารางเวลาที่กำหนดไว้และยังรองรับไวยากรณ์ "cron job" แบบง่ายๆ ฉันประสบความสำเร็จมากมายกับมัน
นี่คือตัวอย่างการใช้งานโดยย่อ:
// Instantiate the Quartz.NET scheduler
var schedulerFactory = new StdSchedulerFactory();
var scheduler = schedulerFactory.GetScheduler();
// Instantiate the JobDetail object passing in the type of your
// custom job class. Your class merely needs to implement a simple
// interface with a single method called "Execute".
var job = new JobDetail("job1", "group1", typeof(MyJobClass));
// Instantiate a trigger using the basic cron syntax.
// This tells it to run at 1AM every Monday - Friday.
var trigger = new CronTrigger(
"trigger1", "group1", "job1", "group1", "0 0 1 ? * MON-FRI");
// Add the job to the scheduler
scheduler.AddJob(job, true);
scheduler.ScheduleJob(trigger);
งานประจำวัน? ดูเหมือนว่ามันควรจะเป็นงานตามกำหนดเวลา (แผงควบคุม) - ไม่จำเป็นต้องใช้บริการที่นี่
ต้องเป็นบริการจริงหรือไม่? คุณสามารถใช้งานที่กำหนดเวลาในตัวในแผงควบคุมของ windows ได้ไหม
วิธีที่ฉันทำได้คือการจับเวลา
เรียกใช้ตัวจับเวลาเซิร์ฟเวอร์ให้ตรวจสอบชั่วโมง / นาทีทุก 60 วินาที
หากเป็นชั่วโมง / นาทีที่ถูกต้องให้เรียกใช้กระบวนการของคุณ
จริงๆแล้วฉันได้สรุปสิ่งนี้ออกเป็นคลาสพื้นฐานที่ฉันเรียกว่า OnceADayRunner
ขอทำความสะอาดโค้ดหน่อยแล้วจะโพสต์ไว้ที่นี่
private void OnceADayRunnerTimer_Elapsed(object sender, ElapsedEventArgs e)
{
using (NDC.Push(GetType().Name))
{
try
{
log.DebugFormat("Checking if it's time to process at: {0}", e.SignalTime);
log.DebugFormat("IsTestMode: {0}", IsTestMode);
if ((e.SignalTime.Minute == MinuteToCheck && e.SignalTime.Hour == HourToCheck) || IsTestMode)
{
log.InfoFormat("Processing at: Hour = {0} - Minute = {1}", e.SignalTime.Hour, e.SignalTime.Minute);
OnceADayTimer.Enabled = false;
OnceADayMethod();
OnceADayTimer.Enabled = true;
IsTestMode = false;
}
else
{
log.DebugFormat("Not correct time at: Hour = {0} - Minute = {1}", e.SignalTime.Hour, e.SignalTime.Minute);
}
}
catch (Exception ex)
{
OnceADayTimer.Enabled = true;
log.Error(ex.ToString());
}
OnceADayTimer.Start();
}
}
เนื้อของวิธีนี้อยู่ในเช็ค e.SignalTime.Minute / Hour
มีตะขออยู่ในนั้นสำหรับการทดสอบ ฯลฯ แต่นี่คือสิ่งที่ตัวจับเวลาที่ผ่านไปของคุณอาจดูเหมือนเพื่อให้ใช้งานได้ทั้งหมด
ตามที่คนอื่นเขียนไปแล้วตัวจับเวลาเป็นตัวเลือกที่ดีที่สุดในสถานการณ์ที่คุณอธิบาย
ทั้งนี้ขึ้นอยู่กับความต้องการของคุณการตรวจสอบเวลาปัจจุบันทุกนาทีอาจไม่จำเป็น หากคุณไม่จำเป็นต้องดำเนินการอย่างตรงไปตรงมาในเวลาเที่ยงคืน แต่เพียงแค่ภายในหนึ่งชั่วโมงหลังเที่ยงคืนคุณสามารถใช้วิธีการของ Martin ในการตรวจสอบว่าวันที่มีการเปลี่ยนแปลงเท่านั้นหรือไม่
หากเหตุผลที่คุณต้องการดำเนินการในเวลาเที่ยงคืนคือคุณคาดว่าปริมาณงานบนคอมพิวเตอร์ของคุณจะเหลือน้อยควรดูแลให้ดีขึ้น: ผู้อื่นมักจะตั้งสมมติฐานเดียวกันนี้และทันใดนั้นคุณก็มีการดำเนินการล้างข้อมูล 100 ครั้งเริ่มตั้งแต่เวลา 00:00 ถึง 0:00 น. : 01 น
ในกรณีนี้คุณควรพิจารณาเริ่มการล้างข้อมูลในเวลาอื่น ฉันมักจะทำสิ่งเหล่านั้นไม่ใช่เวลานาฬิกา แต่เป็นเวลาครึ่งชั่วโมง (1.30 น. เป็นความชอบส่วนตัวของฉัน)
ฉันขอแนะนำให้คุณใช้ตัวจับเวลา แต่ตั้งค่าให้ตรวจสอบทุกๆ 45 วินาทีไม่ใช่นาที มิฉะนั้นคุณอาจพบกับสถานการณ์ที่มีภาระหนักการตรวจสอบสำหรับนาทีใดนาทีหนึ่งจะพลาดเพราะระหว่างเวลาที่ตัวจับเวลาทริกเกอร์กับเวลาที่รหัสของคุณทำงานและตรวจสอบเวลาปัจจุบันคุณอาจพลาดนาทีเป้าหมาย
คุณยังสามารถลอง TaskSchedulerLibrary ได้ที่นี่http://visualstudiogallery.msdn.microsoft.com/a4a4f042-ffd3-42f2-a689-290ec13011f8
ใช้คลาสนามธรรมAbstractScheduledTask
และเรียกScheduleUtilityFactory.AddScheduleTaskToBatch
วิธีการแบบคงที่
สำหรับผู้ที่พบว่าโซลูชันข้างต้นใช้งานไม่ได้นั่นเป็นเพราะคุณอาจมีthis
ในชั้นเรียนของคุณซึ่งแสดงถึงวิธีการขยายซึ่งตามที่ข้อความแสดงข้อผิดพลาดระบุว่าเหมาะสมกับคลาสคงที่ที่ไม่ใช่ทั่วไปเท่านั้น ชั้นเรียนของคุณไม่คงที่ สิ่งนี้ดูเหมือนจะไม่สมเหตุสมผลในฐานะวิธีการขยายเนื่องจากมันทำงานกับอินสแตนซ์ที่เป็นปัญหาดังนั้นให้ลบไฟล์this
.
ลองสิ่งนี้:
public partial class Service : ServiceBase
{
private Timer timer;
public Service()
{
InitializeComponent();
}
protected override void OnStart(string[] args)
{
SetTimer();
}
private void SetTimer()
{
if (timer == null)
{
timer = new Timer();
timer.AutoReset = true;
timer.Interval = 60000 * Convert.ToDouble(ConfigurationManager.AppSettings["IntervalMinutes"]);
timer.Elapsed += new ElapsedEventHandler(timer_Elapsed);
timer.Start();
}
}
private void timer_Elapsed(object source, System.Timers.ElapsedEventArgs e)
{
//Do some thing logic here
}
protected override void OnStop()
{
// disposed all service objects
}
}