दैनिक कार्य करने के लिए मैं C # Windows सेवा कैसे शेड्यूल कर सकता हूं?


84

मेरे पास C # (.NET 1.1) में लिखी गई सेवा है और मैं चाहता हूं कि यह हर रात आधी रात को कुछ सफाई कार्य करे। मुझे सेवा के भीतर सभी कोड रखने होंगे, इसलिए इसे पूरा करने का सबसे आसान तरीका क्या है? Thread.Sleep()समय-समय पर रोलिंग के लिए उपयोग और जाँच?


10
आप वास्तव में एक .NET प्रक्रिया बनाना चाहते हैं, जो पूरे दिन स्मृति में बैठती है, और आधी रात को कुछ करती है? अपने उपकरण को स्थापित करने पर, आप आधी रात (या कुछ अन्य कॉन्फ़िगर करने योग्य समय) में आग लगाने वाले सिस्टम इवेंट को सेट नहीं कर सकते हैं, जो आपके ऐप को शुरू करता है, उसकी बात करता है, फिर चला जाता है?
राबर्ट पी

6
मुझे पता है कि अगर मुझे पता चला कि मैं एक प्रबंधित सेवा कर रहा हूँ, तो मुझे 20-40 मेगापिक्सेल मेमोरी की खपत होती है, जो हर समय चलती है, जो दिन में एक बार छोड़कर कुछ भी नहीं करता है। :)
राबर्ट पी।

इसकी डुप्लिकेट लिंक
csa

जवाबों:


86

मैं 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();
    }
}

28
क्या समय को जाँचने के लिए हर मिनट को जगाने के बजाय आधी रात को समाप्त होने के लिए टाइमर को सेट करना अधिक समझदारी नहीं होगी?
किबी

11
@ तिब्बती: हो सकता है कि यदि सेवा आधी रात को (जो भी कारण हो) नहीं चल रही है, तो आप जल्द से जल्द सेवा को फिर से चलाना चाहेंगे।
M4N

4
फिर आपको सेवा का स्टार्ट-अप में कुछ कोड जोड़ना चाहिए ताकि पता चल सके कि आपको तुरंत चलना चाहिए, क्योंकि सेवा नहीं चल रही थी, और यह होना चाहिए। आपको हर 10 मिनट में लगातार जाँच नहीं करनी चाहिए। जांचें कि क्या आपको स्टार्टअप पर चलना चाहिए, और फिर चलाने के लिए अगली बार पता न करें। उसके बाद, और जब तक आपको ज़रूरत हो तब तक के लिए एक टाइमर सेट करें।
किबी

3
@ तिब्बती: हाँ मैं सहमत हूँ (यह एक छोटा विवरण है जिसकी हम चर्चा कर रहे हैं)। लेकिन अगर टाइमर हर 10 सेकंड में फायर करता है, तो भी यह कोई नुकसान नहीं करेगा (यानी यह समय लेने वाला नहीं है)।
M4N

1
अच्छा समाधान लेकिन ऊपर दिया गया कोड गायब है _timer.start () और _lastRun को कल इस तरह सेट किया जाना चाहिए: निजी DateTime _lastRun = DateTime.Now.AddDays (-1);
ज़ुलु Z

72

की जाँच करें Quartz.NET । आप इसे Windows सेवा के भीतर उपयोग कर सकते हैं। यह आपको कॉन्फ़िगर शेड्यूल के आधार पर नौकरी चलाने की अनुमति देता है, और यह एक सरल "क्रोन जॉब" सिंटैक्स का भी समर्थन करता है। मुझे इसके साथ बहुत सफलता मिली है।

यहाँ इसके उपयोग का एक त्वरित उदाहरण है:

// 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);

2
एक अच्छा सुझाव - जैसे ही आप कुछ और अधिक जटिल करते हैं बुनियादी टाइमर सामान की तुलना में आपको क्वार्ट्ज देखना चाहिए।
सर्ग 10

2
क्वार्ट्ज का उपयोग करना इतना आसान है, मेरा तर्क है कि एक सुपर-सरल कार्य के लिए भी, बस आगे बढ़ें और इसका उपयोग करें। यह शेड्यूलिंग को आसानी से समायोजित करने की क्षमता देगा।
एंडी व्हाइट

सुपर सरल वास्तव में नहीं है? अधिकांश newbies इस समस्या को यहां पकड़ लेंगे stackoverflow.com/questions/24628372/…
एमिल

21

एक दैनिक कार्य? ऐसा लगता है कि यह केवल एक निर्धारित कार्य (नियंत्रण कक्ष) होना चाहिए - यहां किसी सेवा की आवश्यकता नहीं है।


15

क्या यह एक वास्तविक सेवा होना चाहिए? क्या आप केवल विंडोज़ कंट्रोल पैनल में अनुसूचित कार्यों में निर्मित उपयोग कर सकते हैं।


चूंकि सेवा पहले से मौजूद है, इसलिए वहां कार्यक्षमता जोड़ना आसान हो सकता है।
M4N

1
इस तरह के एक संकीर्ण उद्देश्य सेवा को सांत्वना ऐप में परिवर्तित करना तुच्छ होना चाहिए।
स्टीफन मार्टिन

7
उन्होंने पहले ही कहा, "मुझे सेवा के भीतर सभी कोड को रखना होगा"। मुझे नहीं लगता कि मूल आवश्यकताओं पर सवाल उठाना आवश्यक है। यह निर्भर करता है, लेकिन कभी-कभी किसी निर्धारित कार्य पर सेवा का उपयोग करने के बहुत अच्छे कारण होते हैं।
jeremcc

3
+1: क्योंकि आपको अपनी समस्याओं को हर तरफ से देखने की आवश्यकता है।
GvS

6
यदि मेरे पास प्रति दिन चलने के लिए केवल एक ही कार्य था , तो मुझे लगता है कि एक निर्धारित कार्य के साथ चलने वाला एक सरल कंसोल ऐप ठीक होगा। मेरा कहना है कि यह सब स्थिति पर निर्भर करता है, और यह कहना कि "विंडोज़ सेवा का उपयोग न करें" एक उपयोगी उत्तर नहीं है IMO।
20

3

जिस तरह से मैं इसे पूरा करता हूं वह एक टाइमर के साथ है।

एक सर्वर टाइमर चलाएँ, यह हर 60 सेकंड में घंटा / मिनट की जाँच करें।

यदि यह सही समय / मिनट है, तो अपनी प्रक्रिया चलाएं।

मैं वास्तव में इस आधार वर्ग में एक बार बाहर हो गया हूं जिसे मैं एक बार OneADayRunner कहता हूं।

मुझे कोड को थोड़ा साफ करने दो और मैं इसे यहाँ पोस्ट करूँगा।

    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();
        }
    }

विधि का गोमांस ई.सिग्नलटाइम में है। एमिन्यूट / आवर चेक।

परीक्षण आदि के लिए वहाँ हुक हैं, लेकिन यह वही है जो आपका बीता हुआ टाइमर यह सब काम करने के लिए पसंद कर सकता है।


व्यस्त सर्वर के कारण थोड़ी देरी से यह घंटा + मिनट मिस हो सकता है।
जॉन बी

1
सच। जब मैंने ऐसा किया, मैंने जाँच की: क्या अब समय 00:00 से अधिक है? यदि हां, तो क्या मुझे नौकरी चलाने के 24 घंटे से अधिक समय हो गया है? यदि ऐसा है, तो काम चलाएं, अन्यथा फिर से प्रतीक्षा करें।
ZombieSheep

2

जैसा कि दूसरों ने पहले ही लिखा है, आपके द्वारा वर्णित परिदृश्य में एक टाइमर सबसे अच्छा विकल्प है।

आपकी सटीक आवश्यकताओं के आधार पर, वर्तमान समय की जाँच करना हर मिनट आवश्यक नहीं हो सकता है। आप कार्रवाई करने के लिए की जरूरत है नहीं वास्तव में आधी रात को, लेकिन सिर्फ आधी रात के बाद एक घंटे के भीतर, आप के लिए जा सकते हैं मार्टिन दृष्टिकोण केवल यह पता चल सके की तारीख बदल गया है की।

यदि आप आधी रात को अपना कार्य करना चाहते हैं, तो यह है कि आप अपने कंप्यूटर पर कम कार्यभार की अपेक्षा करते हैं, बेहतर देखभाल करते हैं: एक ही धारणा अक्सर दूसरों द्वारा बनाई जाती है, और अचानक आपके पास 0:00 और 0 के बीच 100 सफाई क्रियाएं होती हैं। : ०१ बजे

उस स्थिति में आपको एक अलग समय पर अपना सफाई शुरू करने पर विचार करना चाहिए। मैं आमतौर पर घड़ी की घड़ी में नहीं, बल्कि आधे घंटे में (1.30 बजे मेरी व्यक्तिगत पसंद है)


1

मेरा सुझाव है कि आप एक टाइमर का उपयोग करें, लेकिन इसे हर 45 सेकंड में जांचने के लिए सेट करें, मिनट नहीं। अन्यथा आप उन परिस्थितियों में भाग सकते हैं जहां भारी भार के साथ, किसी विशेष मिनट के लिए चेक छूट जाता है, क्योंकि समय के बीच टाइमर ट्रिगर होता है और जिस समय आपका कोड चलता है और वर्तमान समय की जांच करता है, आप लक्ष्य मिनट से चूक गए होंगे।


यदि आप यह सुनिश्चित करने के लिए जांच नहीं कर रहे हैं कि यह पहले से ही एक बार नहीं चला है, तो संभावित है कि यदि आप कभी भी 45 सेकंड की जाँच कर रहे हैं तो आप 00:00 को दो बार मार सकते हैं।
माइकल मीडोज

अच्छी बात। जाँच प्रक्रिया के अंत में स्लीप (15000) पर कॉल करके इस समस्या से बचा जा सकता है। (या शायद 16000 एमएस, बस सुरक्षित पक्ष पर होने के लिए ;-)
ट्रेब

मैं सहमत हूँ, आपको यह देखना चाहिए कि यह पहले से ही चल रहा है, भले ही आप किस टाइमर अवधि को चुनें।
GWLlosa


0

उन लोगों के लिए जो उपरोक्त समाधानों को काम नहीं करते हैं, यह इसलिए है क्योंकि आपके पास thisआपकी कक्षा हो सकती है , जो एक विस्तार विधि का अर्थ है, जो त्रुटि संदेश कहता है, केवल गैर-सामान्य स्थिर वर्ग पर समझ में आता है। आपकी कक्षा स्थिर नहीं है। यह ऐसा कुछ प्रतीत नहीं होता है जो एक विस्तार विधि के रूप में समझ में आता है, क्योंकि यह उदाहरण में प्रश्न पर कार्य कर रहा है, इसलिए इसे हटा दें this


-2

इसे इस्तेमाल करे:

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
    }
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.