প্রতিদিন কোনও কাজ সম্পাদনের জন্য আমি কীভাবে সি # উইন্ডোজ পরিষেবা নির্ধারণ করতে পারি?


84

আমার কাছে সি # (.NET 1.1) তে লিখিত একটি পরিষেবা আছে এবং এটি প্রতি রাতে মধ্যরাতে কিছু পরিস্কার কর্ম সম্পাদন করতে চাই। আমাকে পরিষেবাটির মধ্যে থাকা সমস্ত কোড রাখতে হবে, তবে এটি সম্পাদন করার সহজতম উপায় কী? Thread.Sleep()সময়টি রোলিংয়ের জন্য ব্যবহার এবং চেক করছেন?


10
আপনি সত্যিই একটি নেট প্রক্রিয়া তৈরি করতে চান যা সারা দিন স্মৃতিতে বসে থাকে এবং মধ্যরাতে কিছু করে? আপনি কেন আপনার সরঞ্জাম ইনস্টল করার পরে ঠিক এমন একটি সিস্টেম ইভেন্ট সেট আপ করতে পারবেন না যা মধ্যরাতে (বা অন্য কোনও কনফিগারযোগ্য সময়ে) আগুন লাগবে যা আপনার অ্যাপ্লিকেশন শুরু করে, তার কাজটি করে, তারপর চলে যায়?
রবার্ট পি

6
আমি জানি যে আমি কিছুটা হতাশ হব যদি আমি জানতে পারি যে আমার পরিচালিত পরিষেবাটি 20-40 মেগা মেমরি গ্রাস করে, সারাক্ষণ চলমান থাকে যা দিনে একবার ছাড়া কিছুই করে না। :)
রবার্ট পি

এর সদৃশ লিঙ্ক
সিএসএ

উত্তর:


86

আমি থ্রেড.স্লিপ () ব্যবহার করব না। হয় একটি নির্ধারিত টাস্কটি ব্যবহার করুন (যেমন অন্যরা উল্লেখ করেছেন), বা আপনার সার্ভিসের ভিতরে একটি টাইমার স্থাপন করুন যা পর্যায়ক্রমে আগুন লাগে (উদাহরণস্বরূপ প্রতি 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
@ কিবিবি: সম্ভবত যদি মধ্যরাতে পরিষেবা (কোনও কারণেই না) চালিত হয়, তবে আপনি আবার পরিষেবাটি চালু হওয়ার সাথে সাথে আপনি এই কাজটি সম্পাদন করতে চাইতে পারেন।
এম 4 এন

4
তারপরে আপনাকে পরিষেবাটি শুরু করার সময় কিছুটা কোড যুক্ত করা উচিত আপনার এখনই চালানো উচিত কিনা তা নির্ধারণ করার জন্য, কারণ পরিষেবাটি চালু ছিল না, এবং এটি হওয়া উচিত। আপনার প্রতি 10 মিনিট একটানা পরীক্ষা করা উচিত নয়। আপনার প্রারম্ভকালে চালানো উচিত কিনা তা পরীক্ষা করুন এবং তারপরে পরের বার চালানোর জন্য যদি তা খুঁজে না পান। এর পরে, এবং আপনার প্রয়োজন এমন দীর্ঘ সময়ের জন্য একটি টাইমার সেট করুন।
কিব্বি

4
@ কিব্বি: হ্যাঁ আমি সম্মতি জানাই (এটি একটি সামান্য বিশদ যা আমরা আলোচনা করছি)। এমনকি টাইমার প্রতি 10 সেকেন্ডে আগুন লাগলে তা কোনও ক্ষতি করে না (যেমন এটি সময় সাপেক্ষ নয়)।
এম 4 এন

4
ভাল সমাধান তবে উপরের কোডটি নিখোঁজ রয়েছে _timer.start () এবং _lastRun এর জন্য গতকাল সেট করা উচিত: ব্যক্তিগত ডেটটাইম _ালাস্টার = ডেটটাইম.নো.এডডাইজস (-1);
জুলু জেড

72

পরীক্ষা করে দেখুন Quartz.NET । আপনি এটি একটি উইন্ডোজ পরিষেবাতে ব্যবহার করতে পারেন। এটি আপনাকে একটি কনফিগার করা তফসিলের উপর ভিত্তি করে কাজ চালানোর অনুমতি দেয় এবং এটি একটি সাধারণ "ক্রোন জব" সিনট্যাক্সকে সমর্থন করে। আমি এটি দিয়ে অনেক সাফল্য পেয়েছি।

এটির ব্যবহারের একটি দ্রুত উদাহরণ এখানে:

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

4
একটি ভাল পরামর্শ - যত তাড়াতাড়ি আপনি কোয়ার্টজকে লক্ষ্য করা উচিত বুনিয়াদি টাইমার স্টাফের থেকে কিছুটা জটিল কিছু করার সাথে সাথে।
সার্জ 10

4
কোয়ার্টজটি ব্যবহার করা এত সহজ, আমি যুক্তি দিয়েছিলাম যে এমনকি একটি অতি-সাধারণ কাজের জন্য, কেবল এগিয়ে যান এবং এটি ব্যবহার করুন। এটি শিডিউল সহজেই সামঞ্জস্য করার ক্ষমতা দেবে।
অ্যান্ডি হোয়াইট

সুপার কি আসলেই না? Newbies বেশিরভাগই এখানে এই সমস্যাটি দেখতে পাবেন stackoverflow.com/questions/24628372/…
এমিল

21

প্রতিদিনের কাজ? এটির মতো মনে হ'ল এটি একটি নির্ধারিত টাস্ক (কন্ট্রোল প্যানেল) হওয়া উচিত - এখানে কোনও পরিষেবার প্রয়োজন নেই।


15

এটি কি প্রকৃত পরিষেবা হতে হবে? আপনি কি উইন্ডোজ কন্ট্রোল প্যানেলে নির্ধারিত কাজগুলিতে সবেমাত্র ব্যবহার করতে পারেন।


যেহেতু পরিষেবাটি ইতিমধ্যে বিদ্যমান, তাই সেখানে কার্যকারিতা যুক্ত করা আরও সহজ হতে পারে।
এম

4
এর মতো সংকীর্ণ উদ্দেশ্যে পরিষেবাটি কনসোল অ্যাপে রূপান্তর করা তুচ্ছ হওয়া উচিত।
স্টিফেন মার্টিন

7
তিনি ইতিমধ্যে বলেছিলেন, "আমাকে পরিষেবাটির মধ্যে থাকা সমস্ত কোড রাখতে হবে"। আসল প্রয়োজনীয়তা নিয়ে প্রশ্ন করা দরকার বলে মনে করি না। এটি নির্ভর করে, তবে কখনও কখনও নির্ধারিত কোনও কাজের জন্য কোনও পরিষেবা ব্যবহারের জন্য খুব ভাল কারণ রয়েছে।
জেরেমেক 16

4
+1: কারণ আপনাকে সর্বদাই আপনার সমস্যাগুলি চারদিক থেকে দেখার প্রয়োজন।
জিভিএস

6
যদি আমার সত্যিই প্রতিদিন চালানোর জন্য কেবল একটি কাজ ছিল তবে আমি অনুমান করি একটি নির্ধারিত টাস্ক সহ একটি সাধারণ কনসোল অ্যাপ্লিকেশন রান করা ভাল। আমার বক্তব্যটি হ'ল এটি সমস্ত পরিস্থিতির উপর নির্ভর করে এবং "উইন্ডোজ পরিষেবা ব্যবহার করবেন না" বলা কোনও কার্যকর উত্তর আইএমও নয়।
জেরেমেক

3

আমি যেভাবে এটি সম্পাদন করছি তা টাইমার সহ।

একটি সার্ভার টাইমার চালান, এটি প্রতি 60 সেকেন্ডে আওয়ার / মিনিট পরীক্ষা করে দেখুন।

যদি এটি সঠিক সময় / মিনিট হয় তবে আপনার প্রক্রিয়াটি চালান।

আমি আসলে এটি বেস্ট ক্লাসে বিমূর্তভাবে বের করে এনেছি ওনসনে ডায়ার্নার call

আমাকে কোডটি কিছুটা পরিষ্কার করতে দিন এবং আমি এটি এখানে পোস্ট করব।

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

পদ্ধতির গোমাংসটি ই সিগন্যালটাইম.মিনিট / আওয়ার চেক এ রয়েছে।

টেস্টিং ইত্যাদির জন্য সেখানে হুক রয়েছে তবে এটি যা আপনার টাইপ করা টাইমারটিকে সমস্ত কাজ করার মতো দেখতে পারে।


ব্যস্ত সার্ভারের কারণে সামান্য বিলম্বের কারণে এটি ঘন্টা + মিনিট মিস করতে পারে।
জন বি

4
সত্য। যখন আমি এটি করেছি, আমি পরীক্ষা করেছিলাম: এখন সময় কি 00:00 এর চেয়ে বেশি? যদি তাই হয়, আমি সর্বশেষে কাজটি চালিয়েছি 24 ঘন্টােরও বেশি কি? যদি তা হয় তবে কাজটি চালাও, না হলে আবার অপেক্ষা করুন।
জম্বিশিপ

2

অন্যরা ইতিমধ্যে লিখেছেন, আপনার বর্ণনার দৃশ্যের একটি টাইমার হ'ল সর্বোত্তম বিকল্প।

আপনার সঠিক প্রয়োজনীয়তার উপর নির্ভর করে, প্রতি মিনিটে বর্তমান সময়টি পরীক্ষা করা প্রয়োজন হতে পারে না। আপনার যদি ঠিক মধ্যরাতে অ্যাকশনটি সম্পাদন করার প্রয়োজন না হয় তবে মধ্যরাতের ঠিক এক ঘন্টার মধ্যে আপনি কেবল তারিখ পরিবর্তন করেছেন কিনা তা পরীক্ষা করে দেখার জন্য মার্টিনের কাছে যেতে পারেন।

আপনি যদি মধ্যরাতে আপনার ক্রিয়াটি সম্পাদন করতে চান তার কারণ আপনি যদি কম্পিউটারে কম কাজের চাপ আশা করেন তবে ভাল যত্ন নিন: একই ধারণা প্রায়শই অন্যদের দ্বারা করা হয় এবং হঠাৎ আপনার 100 টি ক্লিনআপ ক্রিয়া 0:00 থেকে 0 এর মধ্যে শুরু হয় k : সকাল ১১ টা

সেক্ষেত্রে আপনার অন্য সময় পরিষ্কার করা শুরু করা উচিত। আমি সাধারণত এই জিনিসগুলি ঘড়ির সময় না করে, তবে আধ ঘন্টা সময় করি (সকাল 1.30 টা আমার ব্যক্তিগত পছন্দ হিসাবে)


1

আমি আপনাকে পরামর্শ দিচ্ছি যে আপনি একটি টাইমার ব্যবহার করুন, তবে এটি প্রতি 45 সেকেন্ডের জন্য পরীক্ষা করুন, মিনিট নয়। অন্যথায় আপনি এমন পরিস্থিতিতে পড়তে পারেন যেখানে ভারী বোঝা সহ, একটি নির্দিষ্ট মিনিটের জন্য চেকটি মিস হয়ে যায়, কারণ টাইমারটি ট্রিগার শুরু করে এবং আপনার কোডটি চলমান সময় যাচাই করে ওঠার মধ্যে আপনি লক্ষ্য মুহূর্তটি মিস করতে পারেন।


আপনি যদি এটি ইতিমধ্যে একবারে চালিত না হয় তা নিশ্চিত করতে যাচাই না করে থাকেন, যদি আপনি 45 সেকেন্ড কখনও পরীক্ষা করে থাকেন তবে আপনি 00:00 বার দুবার আঘাত করতে পারেন।
মাইকেল Meadows

ভাল যুক্তি. চেকিংয়ের প্রক্রিয়া শেষে ঘুম (15000) কল করে এই সমস্যা এড়ানো যেতে পারে। (অথবা সম্ভবত 16000 এমএস, কেবল নিরাপদ দিকে থাকতে হবে ;-)
ট্রাব

আমি সম্মত, আপনি টাইমার সময়কাল যা বেছে নিচ্ছেন তা নির্বিশেষে আপনার এটি ইতিমধ্যে চালু আছে কিনা তা পরীক্ষা করা উচিত।
জিডাব্লু্ল্লোসা

0

আপনি এখানে কার্যনির্বাহী লাইব্রেরির চেষ্টা করতে পারেন http://visualstudiogallery.msdn.microsoft.com/a4a4f042-ffd3-42f2-a689-290ec13011f8

বিমূর্ত শ্রেণি প্রয়োগ করুন AbstractScheduledTaskএবং ScheduleUtilityFactory.AddScheduleTaskToBatchস্থিতির পদ্ধতিতে কল করুন


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
    }
}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.