c# - .NET কনসোল অ্যাপ্লিকেশনে কী প্রেসের জন্য শুনুন




console-application (6)

একটি কী চাপ না হওয়া পর্যন্ত কীভাবে আমি আমার কনসোল অ্যাপ্লিকেশনটি চালিয়ে যেতে পারি (যেমন এসসি চাপানো হয়?)

আমি তার একটি লুপ কাছাকাছি আবৃত অনুমান করছি। আমি ReadKey পছন্দ করি না কারণ এটি ক্রিয়াকলাপ বন্ধ করে দেয় এবং কী চাপার পরিবর্তে কী চাপার পরিবর্তে কী চাপার জন্য অনুরোধ করে।

কিভাবে এই কাজ করা যেতে পারে?


অন্যান্য উত্তরগুলির কিছু ভালভাবে পরিচালনা করে না এমন বিষয়গুলির সমাধান:

  • প্রতিক্রিয়াশীল : কীপ্রেস হ্যান্ডলিং কোড সরাসরি নির্বাহ; পোলিং এর বিরলতা বা বিলম্ব ব্লক এড়ানো
  • ঐচ্ছিকতা : গ্লোবাল কীপ্রেসটি বেছে নেওয়া হয় ; অন্যথায় অ্যাপ্লিকেশন সাধারণত প্রস্থান করা উচিত
  • উদ্বেগ বিচ্ছেদ : কম আক্রমণাত্মক শোনার কোড; স্বাভাবিক কনসোল অ্যাপ্লিকেশন কোড স্বাধীনভাবে কাজ করে।

এই পৃষ্ঠার অনেকগুলি সমাধান Console.KeyAvailable ভোট দান করে। উপলব্ধ উপলব্ধ বা Console.KeyAvailable ব্লক করা। Console.ReadKey । যদিও এটি সত্য যে .NET Console এখানে খুব সহযোগী নয়, আপনি Task.Run ব্যবহার করতে পারেন। Task.Run আরও আধুনিক Async মোডের দিকে অগ্রসর হতে।

সচেতন হওয়া প্রধান সমস্যাটি হল, ডিফল্টরূপে, আপনার কনসোল থ্রেড Async অপারেশনের জন্য সেট আপ করা হয় না - অর্থাত যে, যখন আপনি আপনার main ফাংশনের নীচে থেকে পড়ে যান, অ্যাসাইনস সমাপ্তির জন্য অপেক্ষা করার পরিবর্তে, আপনার অ্যাপডম্যান এবং প্রক্রিয়া শেষ হবে। আপনার একক-থ্রেডেড কনসোল প্রোগ্রামে সম্পূর্ণ AsyncContext জন্য স্টিফেন AsyncContext ব্যবহার করতে এটি ঠিক করার একটি উপযুক্ত উপায়। কিন্তু সহজ ক্ষেত্রে, কীপ্রেসটির জন্য অপেক্ষা করার মতো, সম্পূর্ণ trampoline ইনস্টল করা অত্যধিক trampoline হতে পারে।

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

static void Main(String[] args)
{
    Console.WriteLine("Press any key to prevent exit...");
    var tHold = Task.Run(() => Console.ReadKey(true));

    // ... do your console app activity ...

    if (tHold.IsCompleted)
    {
#if false   // For the 'hold' state, you can simply halt forever...
        Console.WriteLine("Holding.");
        Thread.Sleep(Timeout.Infinite);
#else                            // ...or allow continuing to exit
        while (Console.KeyAvailable)
            Console.ReadKey(true);     // flush/consume any extras
        Console.WriteLine("Holding. Press 'Esc' to exit.");
        while (Console.ReadKey(true).Key != ConsoleKey.Escape)
            ;
#endif
    }
}

আপনি আপনার পদ্ধতিটি সামান্য পরিবর্তন করতে পারেন - Console.ReadKey() ব্যবহার করুন। Console.ReadKey() আপনার অ্যাপ্লিকেশনটি বন্ধ করতে, কিন্তু একটি ব্যাকগ্রাউন্ড থ্রেডে আপনার কাজটি করুন:

static void Main(string[] args)
{
    var myWorker = new MyWorker();
    myWorker.DoStuff();
    Console.WriteLine("Press any key to stop...");
    Console.ReadKey();
}

myWorker.DoStuff() ফাংশনে আপনি একটি পটভূমি থ্রেডে অন্য ফাংশনটি আহ্বান করবেন ( Action<>() ব্যবহার করুন অথবা Func<>() এটি একটি সহজ উপায়), তারপরে অবিলম্বে ফিরুন।


আমার অভিজ্ঞতার মতে, কনসোল অ্যাপ্লিকেশানে নিম্নে চাপানো শেষ কীটি পড়ার সবচেয়ে সহজ উপায় হল নিম্নরূপ (তীর কী সহ উদাহরণ):

ConsoleKey readKey = Console.ReadKey ().Key;
if (readKey == ConsoleKey.LeftArrow) {
    <Method1> ();  //Do something
} else if (readKey == ConsoleKey.RightArrow) {
    <Method2> ();  //Do something
}

আমি loops এড়াতে ব্যবহার করি, পরিবর্তে আমি একটি পদ্ধতিতে উপরের কোডটি লিখি, এবং আমি "মেথড 1" এবং "মেথড 2" উভয়ের শেষে এটি কল করি, তাই, "মেথড 1" বা "মেথড 2" কার্যকর করার পরে, কনসোল। ReadKey () । কে আবার কী পড়তে প্রস্তুত।


এখানে আপনি একটি ভিন্ন থ্রেডে কিছু করার জন্য একটি পদ্ধতি এবং একটি ভিন্ন থ্রেডে চাপানো কীটি শুনতে শুরু করুন। এবং যখন আপনার প্রকৃত প্রক্রিয়াটি শেষ হয় অথবা ব্যবহারকারী Esc কী টিপে প্রক্রিয়াটি বন্ধ করে দেয় তখন কনসোল তার প্রক্রিয়াকরণ বন্ধ করবে।

class SplitAnalyser
{
    public static bool stopProcessor = false;
    public static bool Terminate = false;

    static void Main(string[] args)
    {
        Console.ForegroundColor = ConsoleColor.Green;
        Console.WriteLine("Split Analyser starts");
        Console.ForegroundColor = ConsoleColor.Red;
        Console.WriteLine("Press Esc to quit.....");
        Thread MainThread = new Thread(new ThreadStart(startProcess));
        Thread ConsoleKeyListener = new Thread(new ThreadStart(ListerKeyBoardEvent));
        MainThread.Name = "Processor";
        ConsoleKeyListener.Name = "KeyListener";
        MainThread.Start();
        ConsoleKeyListener.Start();

        while (true) 
        {
            if (Terminate)
            {
                Console.WriteLine("Terminating Process...");
                MainThread.Abort();
                ConsoleKeyListener.Abort();
                Thread.Sleep(2000);
                Thread.CurrentThread.Abort();
                return;
            }

            if (stopProcessor)
            {
                Console.WriteLine("Ending Process...");
                MainThread.Abort();
                ConsoleKeyListener.Abort();
                Thread.Sleep(2000);
                Thread.CurrentThread.Abort();
                return;
            }
        } 
    }

    public static void ListerKeyBoardEvent()
    {
        do
        {
            if (Console.ReadKey(true).Key == ConsoleKey.Escape)
            {
                Terminate = true;
            }
        } while (true); 
    }

    public static void startProcess()
    {
        int i = 0;
        while (true)
        {
            if (!stopProcessor && !Terminate)
            {
                Console.ForegroundColor = ConsoleColor.White;
                Console.WriteLine("Processing...." + i++);
                Thread.Sleep(3000);
            }
            if(i==10)
                stopProcessor = true;

        }
    }

}

ভিডিও অভিশাপ বিল্ডিং থেকে .NET কনসোল অ্যাপ্লিকেশনগুলি সি # জেসন রবার্টস এ http://www.pluralsight.com এ

আমরা একাধিক চলমান প্রক্রিয়া অনুসরণ করতে পারে

  static void Main(string[] args)
    {
        Console.CancelKeyPress += (sender, e) =>
        {

            Console.WriteLine("Exiting...");
            Environment.Exit(0);
        };

        Console.WriteLine("Press ESC to Exit");

        var taskKeys = new Task(ReadKeys);
        var taskProcessFiles = new Task(ProcessFiles);

        taskKeys.Start();
        taskProcessFiles.Start();

        var tasks = new[] { taskKeys };
        Task.WaitAll(tasks);
    }

    private static void ProcessFiles()
    {
        var files = Enumerable.Range(1, 100).Select(n => "File" + n + ".txt");

        var taskBusy = new Task(BusyIndicator);
        taskBusy.Start();

        foreach (var file in files)
        {
            Thread.Sleep(1000);
            Console.WriteLine("Procesing file {0}", file);
        }
    }

    private static void BusyIndicator()
    {
        var busy = new ConsoleBusyIndicator();
        busy.UpdateProgress();
    }

    private static void ReadKeys()
    {
        ConsoleKeyInfo key = new ConsoleKeyInfo();

        while (!Console.KeyAvailable && key.Key != ConsoleKey.Escape)
        {

            key = Console.ReadKey(true);

            switch (key.Key)
            {
                case ConsoleKey.UpArrow:
                    Console.WriteLine("UpArrow was pressed");
                    break;
                case ConsoleKey.DownArrow:
                    Console.WriteLine("DownArrow was pressed");
                    break;

                case ConsoleKey.RightArrow:
                    Console.WriteLine("RightArrow was pressed");
                    break;

                case ConsoleKey.LeftArrow:
                    Console.WriteLine("LeftArrow was pressed");
                    break;

                case ConsoleKey.Escape:
                    break;

                default:
                    if (Console.CapsLock && Console.NumberLock)
                    {
                        Console.WriteLine(key.KeyChar);
                    }
                    break;
            }
        }
    }
}

internal class ConsoleBusyIndicator
{
    int _currentBusySymbol;

    public char[] BusySymbols { get; set; }

    public ConsoleBusyIndicator()
    {
        BusySymbols = new[] { '|', '/', '-', '\\' };
    }
    public void UpdateProgress()
    {
        while (true)
        {
            Thread.Sleep(100);
            var originalX = Console.CursorLeft;
            var originalY = Console.CursorTop;

            Console.Write(BusySymbols[_currentBusySymbol]);

            _currentBusySymbol++;

            if (_currentBusySymbol == BusySymbols.Length)
            {
                _currentBusySymbol = 0;
            }

            Console.SetCursorPosition(originalX, originalY);
        }
    }

সবচেয়ে কম উপায়:

Console.WriteLine("Press ESC to stop");

while (!(Console.KeyAvailable && Console.ReadKey(true).Key == ConsoleKey.Escape))
{
    // do something
}

Console.ReadKey() একটি ব্লকিং ফাংশন, এটি প্রোগ্রামটির কার্যকরতা বন্ধ করে এবং একটি কী চাপের জন্য অপেক্ষা করে, তবে Console.KeyAvailable পরীক্ষা করার জন্য ধন্যবাদ। Console.KeyAvailable প্রথম, while লুপটি ব্লক করা হয় না, তবে Esc চাপানো পর্যন্ত চলমান।





console-application