.NET কনসোল অ্যাপটি কীভাবে চলতে হবে?


104

একটি কনসোল অ্যাপ্লিকেশন বিবেচনা করুন যা কিছু পরিষেবা পৃথক থ্রেডে শুরু করে। ব্যবহারকারীকে এটি বন্ধ করার জন্য Ctrl + C টিপতে অপেক্ষা করা দরকার।

নিম্নলিখিতটি করার কোনটি আরও ভাল উপায়?

static ManualResetEvent _quitEvent = new ManualResetEvent(false);

static void Main() {
    Console.CancelKeyPress += (sender, eArgs) => {
        _quitEvent.Set();
        eArgs.Cancel = true;
    };

    // kick off asynchronous stuff 

    _quitEvent.WaitOne();

    // cleanup/shutdown and quit
}

অথবা এটি, থ্রেড.স্লিপ (1) ব্যবহার করে:

static bool _quitFlag = false;

static void Main() {
    Console.CancelKeyPress += delegate {
        _quitFlag = true;
    };

    // kick off asynchronous stuff 

    while (!_quitFlag) {
        Thread.Sleep(1);
    }

    // cleanup/shutdown and quit
}

উত্তর:


63

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

আমি অবশ্যই প্রথমটি বলব।


2
+1 টি। উপরন্তু, যেহেতু boolহিসেবে ঘোষণা করা হয় না volatile, সেখানে নির্দিষ্ট সম্ভাবনা যে পরবর্তী থেকে সার্চ _quitFlagমধ্যে whileলুপ দূরে অপ্টিমাইজ করা হবে একটি অসীম লুপ সৃষ্টি করে।
অ্যাডাম রবিনসন

2
এটি করার জন্য প্রস্তাবিত উপায়টি অনুপস্থিত। আমি উত্তর হিসাবে এটি আশা ছিল।
আইরি ডস অঞ্জোস

30

বিকল্পভাবে, আরও সহজ সমাধান কেবল:

Console.ReadLine();

আমি এটি প্রস্তাব দিতে চলেছিলাম, তবে এটি কেবল
সিটিআরএল


মনে রাখবেন যে 'কনসোল.আডলাইন ()' থ্রেড ব্লক করা। আবেদন এখনও চলমান করা হবে তাই কিন্তু ব্যবহারকারী অপেক্ষা চেয়ে অসম্মতির একটি লাইন লিখুন
fabriciorissetto

2
@ ফ্যাব্রিকিয়রিসেট্টো ওপি প্রশ্নটিতে 'অ্যাসিনক্রোনাস স্টাফ কিক অফ' বলেছে, সুতরাং অ্যাপ্লিকেশনটি অন্য থ্রেডে কাজ করবে
কোকোওয়ালা

1
@ কোকোয়াল্লা আমি এটি মিস করেছি। আমার খারাপ!
ফ্যাবিলিরিসেটটো

12

আপনি এটি করতে পারেন (এবং CancelKeyPressইভেন্ট হ্যান্ডলারটি সরিয়ে ফেলুন ):

while(!_quitFlag)
{
    var keyInfo = Console.ReadKey();
    _quitFlag = keyInfo.Key == ConsoleKey.C
             && keyInfo.Modifiers == ConsoleModifiers.Control;
}

এটি আরও ভাল কিনা তা নিশ্চিত নন তবে Thread.Sleepলুপে কল করার ধারণাটি আমার পছন্দ নয় .. আমি মনে করি এটি ব্যবহারকারীর ইনপুটটিতে ব্লক করা আরও পরিষ্কার।


আমি পছন্দ করি না যে আপনি সিটিআরএল + সি দ্বারা চালিত সিগন্যালের পরিবর্তে Ctrl + C কীগুলি অনুসন্ধান করছেন।
কোডসইনচওস

9

আমি অ্যাপ্লিকেশন ব্যবহার করতে পছন্দ করি

static void Main(string[] args) {

   //Do your stuff here

   System.Windows.Forms.Application.Run();

   //Cleanup/Before Quit
}

ডক্স থেকে:

কোনও ফর্ম ছাড়াই বর্তমান থ্রেডে একটি স্ট্যান্ডার্ড অ্যাপ্লিকেশন বার্তা লুপ চালানো শুরু করে।


9
তবে তারপরে আপনি কেবল উইন্ডোজ ফর্মের উপর নির্ভরশীলতা নিয়ে যান। প্রচলিত। নেট ফ্রেমওয়ার্ক নিয়ে খুব বেশি সমস্যা নেই তবে বর্তমান প্রবণতাটি কেবলমাত্র আপনার প্রয়োজনীয় অংশগুলি সহ মডিউল মোতায়েনের দিকে।
কোডসইনচওস

4

মনে হচ্ছে আপনি এটি আপনার প্রয়োজনের চেয়ে শক্ত করে তুলছেন। Joinআপনি কেবল থ্রেডটি বন্ধ করার ইঙ্গিত দেওয়ার পরে কেন নয় ?

class Program
{
    static void Main(string[] args)
    {
        Worker worker = new Worker();
        Thread t = new Thread(worker.DoWork);
        t.IsBackground = true;
        t.Start();

        while (true)
        {
            var keyInfo = Console.ReadKey();
            if (keyInfo.Key == ConsoleKey.C && keyInfo.Modifiers == ConsoleModifiers.Control)
            {
                worker.KeepGoing = false;
                break;
            }
        }
        t.Join();
    }
}

class Worker
{
    public bool KeepGoing { get; set; }

    public Worker()
    {
        KeepGoing = true;
    }

    public void DoWork()
    {
        while (KeepGoing)
        {
            Console.WriteLine("Ding");
            Thread.Sleep(200);
        }
    }
}

2
আমার ক্ষেত্রে অ্যাসিক্রোনাস স্টাফ চলমান থ্রেডগুলিতে আমি নিয়ন্ত্রণ করি না।
অরবিট

1) আমি পছন্দ করি না আপনি Ctrl + C কীগুলি অনুসন্ধান করছেন, সিটিআরএল + সি দ্বারা চালিত সিগন্যালের পরিবর্তে। ২) যদি অ্যাপ্লিকেশনটি একক কর্মী থ্রেডের পরিবর্তে টাস্ক ব্যবহার করে তবে আপনার দৃষ্টিভঙ্গি কার্যকর হবে না।
কোডসইনচওস

2

বাতিল করার টোকেনের ভিত্তিতে থ্রেড / প্রোগ্রামটি ব্লক করাও সম্ভব।

token.WaitHandle.WaitOne();

টোকেন বাতিল হয়ে গেলে ওয়েটহ্যান্ডলকে সংকেত দেওয়া হয়।

আমি মাইক্রোসফ্ট দ্বারা ব্যবহৃত এই কৌশলটি দেখেছি zআজুরি.ওয়েবজবস.জবহোস্ট, যেখানে টোকনটি ওয়েবজবসুটডাউন ওয়াচারের একটি বাতিলকরণ টোকেন উত্স থেকে আসে (একটি ফাইল প্রহরী যা কাজ শেষ করে)।

প্রোগ্রামটি কখন শেষ হতে পারে তার উপর এটি কিছুটা নিয়ন্ত্রণ দেয়।


1
এটি যে কোনও রিয়েল-ওয়ার্ল্ড কনসোল অ্যাপ্লিকেশনটির জন্য একটি দুর্দান্ত উত্তর যা CTL+Cএটির জন্য শোনার প্রয়োজন কারণ এটি দীর্ঘকাল ধরে চলমান অপারেশন করছে বা একটি ডেমন, এটির কর্মীদের থ্রেডগুলিও নিখুঁতভাবে বন্ধ করে দেওয়া উচিত। আপনি এটি বাতিল টোকেন দিয়ে করবেন এবং সুতরাং এই উত্তরটি WaitHandleএকটি নতুন তৈরির পরিবর্তে ইতিমধ্যে উপস্থিত থাকার সুযোগ নিয়েছে ।
mdisibio

1

দু'জনের মধ্যে প্রথমে ভাল

_quitEvent.WaitOne();

কারণ দ্বিতীয়টিতে থ্রেড জেগে প্রতি এক মিলিসেকেন্ডে ওএস ইন্টারপেটে পরিণত হবে যা ব্যয়বহুল


এটি Consoleযদি আপনার কোন কনসোল সংযুক্ত না করে থাকে তবে এটি পদ্ধতির জন্য একটি ভাল বিকল্প (কারণ উদাহরণস্বরূপ, প্রোগ্রামটি কোনও পরিষেবা দ্বারা শুরু করা হয়েছে)
মার্কো সুলা

0

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

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