0

I am currently writing a console application which uses a lot of multithreading. I want to be able to always allow the user to enter something into the console however, there will be regular output to the console from the threads but I want users to be always able to enter things into the console and for me to handle the input.

How would I achieve this? I've found nothing online about it?

Thanks in advanced!

This is for c# btw!

unsworthpp
  • 45
  • 1
  • 6

1 Answers1

4

Edit. My original answer from several years ago relied on the user typing in a magic string to end the console listener, and overlooked that CTL+C is already the default cancellation signal.

class Program
{
    readonly static CancellationTokenSource _cancelTokenSrc = new CancellationTokenSource();

    static void Main(string[] args)
    {
        // CTL + C is the built-in cancellation for console apps; 
        Console.CancelKeyPress += Console_CancelKeyPress;
        CancellationToken cancelToken = _cancelTokenSrc.Token;

        Console.WriteLine("Type commands followed by 'ENTER'");
        Console.WriteLine("Press CTL+C to Terminate");
        Console.WriteLine();
        try
        {
            // thread that performs background work until cancelled
            Task.Run(() => DoWork(), cancelToken);
            // thread that listens for keyboard input until cancelled
            Task.Run(() => ListenForInput(), cancelToken);
            // continue listening until cancel signal is sent
            cancelToken.WaitHandle.WaitOne();
            cancelToken.ThrowIfCancellationRequested();
        }
        catch (OperationCanceledException)
        {
            Console.WriteLine("Operation Canceled.");
        }
        catch (Exception ex)
        {
            Console.WriteLine($"Error: {ex.Message}");
        }
    }

    static void ListenForInput()
    {
        while (true)
        {
            string userInput = Console.ReadLine();
            if(!String.IsNullOrWhiteSpace(userInput))
                Console.WriteLine($"Executing user command {userInput}...");
        }
    }

    static void DoWork()
    {
        while (true)
        {
            Thread.Sleep(3000);
            Console.WriteLine("Doing work...");
        }
    }

    static void Console_CancelKeyPress(object sender, ConsoleCancelEventArgs e)
    {
        // we want to cancel the default behavior so we can send the cancellation signal
        // to our background threads and not just terminate here
        e.Cancel = true;
        Console.WriteLine("Cancelling...");
        _cancelTokenSrc.Cancel();
    }
}
mdisibio
  • 3,148
  • 31
  • 47
  • no that doesn't work...it just exits when i enter anything into the console? – unsworthpp Apr 06 '14 at 20:52
  • @user3228693 Apologies for the first post that was based on the model of only cancelling a thread by user input. To enter multiple commands, the listener thread will need to run in a loop. I also added a dummy worker thread so that the sample will run and demonstrate the concept. – mdisibio Apr 06 '14 at 21:25