সি # টাইমাররা কি আলাদা থ্রেডে প্রবাহিত হবে?


100

একটি System.Timers.Timer এটি তৈরি হওয়া থ্রেডের চেয়ে পৃথক থ্রেডে কেটে যায়?

আসুন বলুন যে আমার সাথে টাইমার সহ একটি ক্লাস রয়েছে যা প্রতি 5 সেকেন্ডে আগত। টাইমারটি যখন জ্বলতে থাকে, অতিবাহিত পদ্ধতিতে, কিছু অবজেক্ট পরিবর্তন করা হয়। বলুন 10 সেকেন্ডের মতো এই বস্তুটি সংশোধন করতে দীর্ঘ সময় লাগে। এই পরিস্থিতিতে আমি কি থ্রেড সংঘর্ষে দৌড়াব তা কি সম্ভব?


এটি সমস্যার কারণ হতে পারে। মনে রাখবেন, সাধারণভাবে, থ্রেডপুলের থ্রেডগুলি দীর্ঘ-চলমান প্রক্রিয়াগুলির জন্য ডিজাইন করা হয়নি।
গ্রেগ ডি

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

উত্তর:


62

জন্য System.Timers.Timer :

দেখুন নিচের ব্রায়ান গিদিয়োনের উত্তর

জন্য System.Threading.Timer :

টাইমারদের উপর এমএসডিএন ডকুমেন্টেশন বলে:

System.Thareading.Timer বর্গ থ্রেডপুল থ্রেডে কলব্যাকগুলি তৈরি করে এবং ইভেন্টের মডেলটি একেবারেই ব্যবহার করে না।

সুতরাং প্রকৃতপক্ষে টাইমারটি একটি ভিন্ন থ্রেডে বিস্তৃত হয়।


21
সত্য, তবে এটি সম্পূর্ণ আলাদা শ্রেণি। ওপি সিস্টেম.টাইমারস.টাইমার ক্লাস সম্পর্কে জিজ্ঞাসা করেছিল।
ব্রায়ান গিদিওন

4
ওহ আপনি ঠিক. msdn.mic Microsoft.com/en-us/library/system.timers.timer.aspx বলছে "বিচ্ছিন্ন ইভেন্টটি থ্রেডপুলের থ্রেডে উত্থাপিত হয়েছে।" আমি সেখান থেকে একই উপসংহার অনুমান করি।
জোরেেন

6
হ্যাঁ, তবে এটি খুব সহজ নয়। আমার উত্তর দেখুন।
ব্রায়ান গিডন

192

এটা নির্ভর করে. System.Timers.Timerঅপারেশন দুটি মোড আছে।

যদি SynchronizingObjectকোনও ISynchronizeInvokeউদাহরণে সেট করা থাকে তবে Elapsedইভেন্টটি সিঙ্ক্রোনাইজ করা অবজেক্ট হোস্টিং থ্রেডে কার্যকর করা হবে। সাধারণত এই ISynchronizeInvokeদৃষ্টান্তগুলি কেবল পুরানো Controlএবং Formউদাহরণস্বরূপ নয় যেগুলির সাথে আমরা সকলেই পরিচিত। সুতরাং সেই ক্ষেত্রে Elapsedইভেন্টটি ইউআই থ্রেডে আহ্বান করা হয় এবং এটি এর অনুরূপ আচরণ করে System.Windows.Forms.Timer। অন্যথায়, এটি ISynchronizeInvokeব্যবহৃত হয়েছিল নির্দিষ্ট উদাহরণের উপর নির্ভর করে ।

যদি SynchronizingObjectনাল হয় তবে Elapsedইভেন্টটি একটি ThreadPoolথ্রেডে আহ্বান করা হয়েছে এবং এটি এর অনুরূপ আচরণ করে System.Threading.Timer। প্রকৃতপক্ষে, এটি প্রকৃতপক্ষে একটি System.Threading.Timerপর্দা ব্যবহার করে এবং প্রয়োজনে টাইমার কলব্যাক পাওয়ার পরে মার্শালিং অপারেশন করে ।


4
আপনি যদি টাইমার কলব্যাকটি একটি নতুন থ্রেডে চালিত করতে চান, আপনি একটি System.Threading.Timerবা ব্যবহার করবেন System.Timers.Timer?
সিজে

4
@ সিজে:: যে কেউ এটি করতে পারে।
ব্রায়ান গিডন

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

4
প্রত্যেকে ... System.Timers.Timerদুটি পদ্ধতিতে অপারেশন রয়েছে। এটি এলোমেলোভাবে নির্ধারিত থ্রেড পুল থ্রেডে চলতে পারে বা এটি থ্রেডটি হোস্টিং করে যা চালাতে পারে তাতে চলতে পারে ISynchronizeInvoke। কীভাবে এটি আরও পরিষ্কার করা যায় আমি জানি না। System.Threading.Timerমূল প্রশ্নের সাথে সামান্য (যদি কিছু থাকে) করার কিছু আছে।
ব্রায়ান গিডন

@LeandroDeMelloFagundes আপনি ব্যবহার করা যাবে না lockযে জন্য?
ওজকান

24

পূর্ববর্তী কাটিয়ে যাওয়া এখনও চলমান অবধি প্রতিটি বিস্তৃত ইভেন্ট একই থ্রেডে আগুন লাগবে।

সুতরাং এটি আপনার জন্য সংঘর্ষ পরিচালনা করে

এটিকে কনসোলে রাখার চেষ্টা করুন

static void Main(string[] args)
{
    Debug.WriteLine(Thread.CurrentThread.ManagedThreadId);
    var timer = new Timer(1000);
    timer.Elapsed += timer_Elapsed;
    timer.Start();
    Console.ReadLine();
}

static void timer_Elapsed(object sender, ElapsedEventArgs e)
{
    Thread.Sleep(2000);
    Debug.WriteLine(Thread.CurrentThread.ManagedThreadId);
}

আপনি এই জাতীয় কিছু পাবেন

10
6
12
6
12

যেখানে 10 কলিং থ্রেড এবং 6 এবং 12 বিজি অতিক্রান্ত ইভেন্ট থেকে ফায়ার করছে। আপনি যদি থ্রেডটি সরিয়ে ফেলেন leep ঘুম (2000); আপনি এই জাতীয় কিছু পাবেন

10
6
6
6
6

যেহেতু কোনও সংঘর্ষ নেই।

তবে এটি এখনও আপনাকে একটি সমস্যা দিয়ে চলেছে। আপনি যদি প্রতি 5 সেকেন্ডে ইভেন্টটি চালাচ্ছেন এবং সম্পাদনা করতে 10 সেকেন্ড সময় লাগে আপনার কিছু সম্পাদনা এড়াতে কিছু লকিং দরকার।


8
timer.Stop()অতিবাহিত ইভেন্ট পদ্ধতির শুরুতে একটি যোগ করা এবং তারপরে অতিবাহিত ইভেন্ট পদ্ধতির timer.Start()শেষে একটি বিচ্ছিন্ন ইভেন্টটিকে সংঘর্ষ থেকে বিরত রাখবে।
মেট্রো স্মুরফ

4
আপনাকে টাইমর.এসটপ () লাগানোর দরকার নেই কেবল আপনাকে সময় নির্ধারণ করতে হবে .আউটু রিসেট = মিথ্যা; তারপরে আপনি ইভেন্টটি প্রক্রিয়া করার পরে আপনি টাইমার স্টার্ট () তৈরি করুন। আমি মনে করি এটি সংঘর্ষ এড়ানোর একটি ভাল উপায়।
জোও আন্তোনেস

17

System.Timers.Timer এর জন্য আলাদা থ্রেডে সিঙ্ক্রোনাইজিং অবজেক্ট সেট না করা থাকলে।

    static System.Timers.Timer DummyTimer = null;

    static void Main(string[] args)
    {
        try
        {

            Console.WriteLine("Main Thread Id: " + System.Threading.Thread.CurrentThread.ManagedThreadId);

            DummyTimer = new System.Timers.Timer(1000 * 5); // 5 sec interval
            DummyTimer.Enabled = true;
            DummyTimer.Elapsed += new System.Timers.ElapsedEventHandler(OnDummyTimerFired);
            DummyTimer.AutoReset = true;

            DummyTimer.Start();

            Console.WriteLine("Hit any key to exit");
            Console.ReadLine();
        }
        catch (Exception Ex)
        {
            Console.WriteLine(Ex.Message);
        }

        return;
    }

    static void OnDummyTimerFired(object Sender, System.Timers.ElapsedEventArgs e)
    {
        Console.WriteLine(System.Threading.Thread.CurrentThread.ManagedThreadId);
        return;
    }

আউটপুট আপনি দেখতে পাচ্ছেন যে ডামিটাইমারের 5 সেকেন্ডের ব্যবধানে গুলি চালানো হয়েছে:

Main Thread Id: 9
   12
   12
   12
   12
   12
   ... 

সুতরাং, যেমন দেখা গেছে, অনডম্মিটাইমারফায়ার্ড ওয়ার্কার্স থ্রেডে মৃত্যুদন্ড কার্যকর করা হয়েছে।

না, আরও জটিলতা - যদি আপনি 10 এমএস বলতে বিরতি হ্রাস করেন,

Main Thread Id: 9
   11
   13
   12
   22
   17
   ... 

এটি হ'ল কারণ যদি পরবর্তী টিকটি বহিস্কার করা হয় তবে যদি অনডমিটাইমারফায়ার এর পূর্ব নির্বাহ সম্পাদন না করা হয়, তবে। নেট এই কাজটি করার জন্য একটি নতুন থ্রেড তৈরি করবে।

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

http://msdn.microsoft.com/en-us/magazine/cc164015.aspx#S2


এটি একটি ভাল উদাহরণ। আমি এখন অবধি জানি না এবং আমাকে এখানে এবং সেখানে কিছু লক স্থাপন করা দরকার। পারফেক্ট
ওলারু মিরসিয়া

এবং যদি আমি চাই যে টাইমারটি কনসোল অ্যাপ্লিকেশনটির মূল থ্রেডে অতিবাহিত ইভেন্টটি চালিত করে?
জ্যাকট্রিক

13

যদি অতিবাহিত ইভেন্টটি আরও বেশি সময় নেয় তবে বিরতিটি এটি অতিবাহিত ইভেন্টটি বাড়ানোর জন্য অন্য থ্রেড তৈরি করবে। তবে এটির জন্য একটি পরিকল্পনা রয়েছে

static void timer_Elapsed(object sender, ElapsedEventArgs e)    
{     
   try
   {
      timer.Stop(); 
      Thread.Sleep(2000);        
      Debug.WriteLine(Thread.CurrentThread.ManagedThreadId);    
   }
   finally
   {
     timer.Start();
   }
}

+1 সহজ এবং পরিষ্কার উত্তর, তবে এটি সর্বদা কার্যকর হবে না। বরং একটিকে টাইমার লক বা সিঙ্ক্রোনাইজিংঅবজেক্ট সম্পত্তি ব্যবহার করা উচিত।
রোলারকোস্টা 23'17
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.