উইন্ডোজ পরিষেবা ব্যবহারের জন্য সেরা টাইমার


108

আমার কিছু উইন্ডোজ পরিষেবা তৈরি করতে হবে যা প্রতিটি এন পিরিয়ড সময়মত কার্যকর করে।
প্রশ্নটি: আমার
কোন টাইমার নিয়ন্ত্রণ ব্যবহার করা উচিত: System.Timers.Timerবা System.Threading.Timerএকটি? এটি কি কিছু প্রভাবিত করে?

আমি জিজ্ঞাসা করছি কারণ আমি System.Timers.Timerউইন্ডোজ পরিষেবাগুলিতে সঠিক কাজ না করার অনেক প্রমাণ শুনেছি ।
ধন্যবাদ.

উত্তর:


118

উভয় System.Timers.Timerএবং System.Threading.Timerপরিষেবার জন্য কাজ করবে।

টাইমার আপনি এড়াতে চাই System.Web.UI.Timerএবং System.Windows.Forms.Timerযা এএসপি অ্যাপ্লিকেশন এবং WinForms জন্য যথাক্রমে। সেগুলি ব্যবহারের ফলে পরিষেবাটি একটি অতিরিক্ত অ্যাসেম্বলি লোড করবে যা আপনি যে ধরণের অ্যাপ্লিকেশন তৈরি করছেন তার জন্য সত্যই প্রয়োজন হয় না।

System.Timers.Timerনিম্নলিখিত উদাহরণের মতো ব্যবহার করুন (এটিও নিশ্চিত করুন যে টিম রবিনসনের উত্তরে বলা হয়েছে, আবর্জনা সংগ্রহ রোধ করতে আপনি একটি শ্রেণির স্তরের ভেরিয়েবল ব্যবহার করেছেন):

using System;
using System.Timers;

public class Timer1
{
    private static System.Timers.Timer aTimer;

    public static void Main()
    {
        // Normally, the timer is declared at the class level,
        // so that it stays in scope as long as it is needed.
        // If the timer is declared in a long-running method,  
        // KeepAlive must be used to prevent the JIT compiler 
        // from allowing aggressive garbage collection to occur 
        // before the method ends. (See end of method.)
        //System.Timers.Timer aTimer;

        // Create a timer with a ten second interval.
        aTimer = new System.Timers.Timer(10000);

        // Hook up the Elapsed event for the timer.
        aTimer.Elapsed += new ElapsedEventHandler(OnTimedEvent);

        // Set the Interval to 2 seconds (2000 milliseconds).
        aTimer.Interval = 2000;
        aTimer.Enabled = true;

        Console.WriteLine("Press the Enter key to exit the program.");
        Console.ReadLine();

        // If the timer is declared in a long-running method, use
        // KeepAlive to prevent garbage collection from occurring
        // before the method ends.
        //GC.KeepAlive(aTimer);
    }

    // Specify what you want to happen when the Elapsed event is 
    // raised.
    private static void OnTimedEvent(object source, ElapsedEventArgs e)
    {
        Console.WriteLine("The Elapsed event was raised at {0}", e.SignalTime);
    }
}

/* This code example produces output similar to the following:

Press the Enter key to exit the program.
The Elapsed event was raised at 5/20/2007 8:42:27 PM
The Elapsed event was raised at 5/20/2007 8:42:29 PM
The Elapsed event was raised at 5/20/2007 8:42:31 PM
...
 */

আপনি যদি চয়ন করেন তবে আপনি System.Threading.Timerনিম্নলিখিত হিসাবে ব্যবহার করতে পারেন:

using System;
using System.Threading;

class TimerExample
{
    static void Main()
    {
        AutoResetEvent autoEvent     = new AutoResetEvent(false);
        StatusChecker  statusChecker = new StatusChecker(10);

        // Create the delegate that invokes methods for the timer.
        TimerCallback timerDelegate = 
            new TimerCallback(statusChecker.CheckStatus);

        // Create a timer that signals the delegate to invoke 
        // CheckStatus after one second, and every 1/4 second 
        // thereafter.
        Console.WriteLine("{0} Creating timer.\n", 
            DateTime.Now.ToString("h:mm:ss.fff"));
        Timer stateTimer = 
                new Timer(timerDelegate, autoEvent, 1000, 250);

        // When autoEvent signals, change the period to every 
        // 1/2 second.
        autoEvent.WaitOne(5000, false);
        stateTimer.Change(0, 500);
        Console.WriteLine("\nChanging period.\n");

        // When autoEvent signals the second time, dispose of 
        // the timer.
        autoEvent.WaitOne(5000, false);
        stateTimer.Dispose();
        Console.WriteLine("\nDestroying timer.");
    }
}

class StatusChecker
{
    int invokeCount, maxCount;

    public StatusChecker(int count)
    {
        invokeCount  = 0;
        maxCount = count;
    }

    // This method is called by the timer delegate.
    public void CheckStatus(Object stateInfo)
    {
        AutoResetEvent autoEvent = (AutoResetEvent)stateInfo;
        Console.WriteLine("{0} Checking status {1,2}.", 
            DateTime.Now.ToString("h:mm:ss.fff"), 
            (++invokeCount).ToString());

        if(invokeCount == maxCount)
        {
            // Reset the counter and signal Main.
            invokeCount  = 0;
            autoEvent.Set();
        }
    }
}

দুটি উদাহরণই এমএসডিএন পৃষ্ঠা থেকে আসে।


1
আপনি কেন পরামর্শ দিচ্ছেন: জিসি.কিপএলাইভ (এটাইমার);, টিটাইমার হ'ল উদাহরণ পরিবর্তনশীল, তাই উদাহরণস্বরূপ যদি এটি ফর্মের ভেরিয়েবল হয়, তবে ফর্মটি রয়েছে যতক্ষণ না সেখানে সর্বদা এটির রেফারেন্স থাকবে, তাই না?
জিওরজিম

37

এই জন্য একটি পরিষেবা ব্যবহার করবেন না। একটি সাধারণ অ্যাপ্লিকেশন তৈরি করুন এবং এটি চালানোর জন্য একটি নির্ধারিত টাস্ক তৈরি করুন।

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

"আপনি যদি এমন একটি উইন্ডোজ পরিষেবা লিখেন যা একটি টাইমার চালায় তবে আপনার সমাধানটি পুনরায় মূল্যায়ন করা উচিত" "

-জোন গাল্লোয়ে, এএসপি.নেট এমভিসি কমিউনিটি প্রোগ্রাম ম্যানেজার, লেখক, খণ্ডকালীন সুপারহিরো


26
যদি আপনার পরিষেবাটি সারাদিন চালানোর উদ্দেশ্যে হয়, তবে সম্ভবত কোনও পরিষেবা নির্ধারিত কোনও কাজের পরিবর্তে অর্থবোধ করে। অথবা, কোনও পরিষেবা থাকা অ্যাডমিনকে সহজতর করতে এবং অ্যাপ্লিকেশন দলের মতো সচেতন নয় এমন একটি অবকাঠামো গোষ্ঠীর জন্য লগইন করতে পারে। যাইহোক, কোনও পরিষেবা প্রয়োজন বলে এই ধারণাটি নিয়ে জিজ্ঞাসা করা সম্পূর্ণ বৈধ এবং এই নেতিবাচক রেটিংগুলি অনুমোদিত নয় e উভয়কে +1 করুন।
sfuqua

2
@ এমআর ননসেন্স। নির্ধারিত কাজগুলি ওএসের মূল অংশ part আপনার FUD নিজের কাছে রাখুন।

4
@ এমআর: আমি প্রচারক নই, আমি একজন বাস্তববাদী। এবং বাস্তবতা আমাকে শিখিয়েছে যে নির্ধারিত কাজগুলি "অত্যন্ত বগি" নয়। প্রকৃতপক্ষে, সেই ব্যক্তি হিসাবে এটি যে এটি সমর্থন করার জন্য যে দাবি করেছে made অন্যথায়, আপনি যা করছেন তা হ'ল ভয়, অনিশ্চয়তা এবং সন্দেহ ছড়িয়ে দেওয়া।

13
আমি এখানে ছিদ্র adeোকার জন্য ঘৃণা করি, তবে আমাকে কিছুটা এমআর ডিফেন্স করতে হবে। আমার সংস্থায় বেশ কয়েকটি সমালোচনামূলক অ্যাপ্লিকেশন রয়েছে যা উইন্ডোজ কনসোল অ্যাপ্লিকেশন। আমি সেগুলি চালানোর জন্য উইন্ডোজ টাস্ক শিডিয়ুলার ব্যবহার করেছি। কমপক্ষে ৫ টি উপলক্ষে এখন আমাদের একটি সমস্যা হয়েছে যেখানে শিডিয়ুলার পরিষেবাটি কোনওভাবে "বিভ্রান্ত হয়ে পড়ে"। কার্যগুলি কার্যকর হয়নি এবং কিছু অদ্ভুত অবস্থায় ছিল। একমাত্র সমাধানটি ছিল সার্ভারের পুনরায় বুট করা বা সময়সূচী পরিষেবাটি বন্ধ করা এবং শুরু করা। প্রশাসনের অধিকার ব্যতীত আমি কিছু করতে পারি এবং উত্পাদন পরিবেশে গ্রহণযোগ্য নয়। শুধু আমার 0.02 ডলার।
SpaceCowboy74

6
এটি আসলে আমার সাথে কয়েকটি সার্ভারে হয়েছে (এখনও 3 টি)। যদিও এটি আদর্শ নয়। কখনও কখনও কেবল বলার কিছু করার নিজের নিজস্ব পদ্ধতি প্রয়োগ করা খারাপ নয়।
SpaceCowboy74

7

হয় একটি কাজ ঠিক করা উচিত। আসলে, System.Threading.Timer অভ্যন্তরীণভাবে System.Timers.Timer ব্যবহার করে।

এটি বলার পরে, সিস্টেম.Timers.Timer এর অপব্যবহার করা সহজ। আপনি যদি কোথাও কোনও ভেরিয়েবলে টাইমার অবজেক্টটি সংরক্ষণ না করেন তবে আবর্জনা সংগ্রহ করা দায়বদ্ধ। যদি এটি হয়, আপনার টাইমার আর আগুন লাগবে না। টাইমারটি বন্ধ করতে ডিসপোজ পদ্ধতিটি কল করুন বা System.Threading.Timer ক্লাসটি ব্যবহার করুন, এটি সামান্য উত্তম র‌্যাপার।

এখন পর্যন্ত কোন সমস্যাগুলি আপনি দেখেছেন?


একটি উইন্ডোজ ফোন অ্যাপ্লিকেশন কেবলমাত্র সিস্টেম.ট্রেডিং.Timer এ অ্যাক্সেস করতে পারে তা আমাকে বিস্মিত করে।
স্টোনটিপ

উইন্ডোজ ফোনগুলির ফ্রেমওয়ার্কটির সম্ভবত একটি হালকা সংস্করণ রয়েছে, উভয় পদ্ধতি ব্যবহার করতে সক্ষম হবার জন্য সমস্ত অতিরিক্ত কোড থাকা সম্ভবত সম্ভবত প্রয়োজন হয় না কারণ এটি অন্তর্ভুক্ত নয়। আমি মনে করি যে নিকের উত্তরটি, উইন্ডোজ ফোনগুলিতে অ্যাক্সেস না পাওয়ার আরও ভাল কারণ দেয় System.Timers.Timerকারণ এটি এতে ফেলে দেওয়া ব্যতিক্রমগুলি পরিচালনা করবে না।
মালাচি

2

আমি পূর্ববর্তী মন্তব্যের সাথে একমত, যা ভিন্ন পদ্ধতির বিবেচনা করা ভাল। আমার পরামর্শটি একটি কনসোল অ্যাপ্লিকেশন লিখতে হবে এবং উইন্ডোজ শিডিউল ব্যবহার করবে:

এটা হবে:

  • নদীর গভীরতানির্ণয় কোডটি হ্রাস করুন যা শিডিয়ুলার আচরণের প্রতিলিপি করে
  • সময়সূচী আচরণের ক্ষেত্রে বৃহত্তর নমনীয়তা সরবরাহ করুন (উদাহরণস্বরূপ কেবল উইকএন্ডে চালানো হবে) অ্যাপ্লিকেশন কোড থেকে বাদ দেওয়া সমস্ত শিডিয়ুলিং লজিক সহ
  • কনফিগারেশন ফাইলগুলিতে কনফিগারেশন মান সেটআপ না করে প্যারামিটারগুলির জন্য কমান্ড লাইন আর্গুমেন্ট ব্যবহার করুন
  • উন্নয়নের সময় ডিবাগ / টেস্ট করা অনেক সহজ
  • কোনও সমর্থন ব্যবহারকারীকে সরাসরি কনসোল অ্যাপ্লিকেশনটি চালুর মাধ্যমে মঞ্জুরি দিন (উদাহরণস্বরূপ সমর্থন পরিস্থিতিতে কার্যকর)

3
তবে এর জন্য কি একজন লগ-ইন ব্যবহারকারীর প্রয়োজন? সুতরাং সার্ভিসে 24/7 চলমান থাকলে পরিষেবাটি আরও ভাল।
জেপি হেলেনমস

1

ইতিমধ্যে উভয়ই বলা হয়েছে System.Threading.Timerএবং System.Timers.Timerকাজ করবে। দুজনের মধ্যে বড় পার্থক্যটি System.Threading.Timerহ'ল অন্যটির চারপাশে একটি মোড়ক।

System.Threading.Timerআরও ব্যতিক্রম হ্যান্ডলিং থাকবে এবং System.Timers.Timerসমস্ত ব্যতিক্রম গ্রাস করবে।

এটি অতীতে আমাকে বড় সমস্যা দিয়েছে তাই আমি সর্বদা 'System.Threading.Timer' ব্যবহার করব এবং এখনও আপনার ব্যতিক্রমগুলি খুব ভালভাবে পরিচালনা করব।


0

আমি জানি যে এই থ্রেডটি কিছুটা পুরাতন তবে এটি আমার একটি নির্দিষ্ট দৃশ্যের জন্য কার্যকর হয়েছিল এবং আমি মনে করেছি যে এটির জন্য System.Threading.Timerএকটি ভাল দৃষ্টিভঙ্গির কারণ থাকার আরও একটি কারণ রয়েছে to যখন আপনাকে পর্যায়ক্রমে একটি কাজ সম্পাদন করতে হবে যা একটি দীর্ঘ সময় নিতে পারে এবং আপনি নিশ্চিত করতে চান যে পুরো অপেক্ষার সময়কাল চাকরির মধ্যে ব্যবহৃত হয়েছে বা আপনি যদি আগের কাজটি শেষ না হওয়ার আগে কাজটি আবার চালানোর জন্য চান না যেখানে কাজটি টাইমার পিরিয়ডের চেয়ে বেশি সময় নেয়। আপনি নিম্নলিখিত ব্যবহার করতে পারেন:

using System;
using System.ServiceProcess;
using System.Threading;

    public partial class TimerExampleService : ServiceBase
    {
        private AutoResetEvent AutoEventInstance { get; set; }
        private StatusChecker StatusCheckerInstance { get; set; }
        private Timer StateTimer { get; set; }
        public int TimerInterval { get; set; }

        public CaseIndexingService()
        {
            InitializeComponent();
            TimerInterval = 300000;
        }

        protected override void OnStart(string[] args)
        {
            AutoEventInstance = new AutoResetEvent(false);
            StatusCheckerInstance = new StatusChecker();

            // Create the delegate that invokes methods for the timer.
            TimerCallback timerDelegate =
                new TimerCallback(StatusCheckerInstance.CheckStatus);

            // Create a timer that signals the delegate to invoke 
            // 1.CheckStatus immediately, 
            // 2.Wait until the job is finished,
            // 3.then wait 5 minutes before executing again. 
            // 4.Repeat from point 2.
            Console.WriteLine("{0} Creating timer.\n",
                DateTime.Now.ToString("h:mm:ss.fff"));
            //Start Immediately but don't run again.
            StateTimer = new Timer(timerDelegate, AutoEventInstance, 0, Timeout.Infinite);
            while (StateTimer != null)
            {
                //Wait until the job is done
                AutoEventInstance.WaitOne();
                //Wait for 5 minutes before starting the job again.
                StateTimer.Change(TimerInterval, Timeout.Infinite);
            }
            //If the Job somehow takes longer than 5 minutes to complete then it wont matter because we will always wait another 5 minutes before running again.
        }

        protected override void OnStop()
        {
            StateTimer.Dispose();
        }
    }

    class StatusChecker
        {

            public StatusChecker()
            {
            }

            // This method is called by the timer delegate.
            public void CheckStatus(Object stateInfo)
            {
                AutoResetEvent autoEvent = (AutoResetEvent)stateInfo;
                Console.WriteLine("{0} Start Checking status.",
                    DateTime.Now.ToString("h:mm:ss.fff"));
                //This job takes time to run. For example purposes, I put a delay in here.
                int milliseconds = 5000;
                Thread.Sleep(milliseconds);
                //Job is now done running and the timer can now be reset to wait for the next interval
                Console.WriteLine("{0} Done Checking status.",
                    DateTime.Now.ToString("h:mm:ss.fff"));
                autoEvent.Set();
            }
        }
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.