C# 取消按键-接受输入

C# 取消按键-接受输入,c#,events,.net-core,C#,Events,.net Core,在编写控制台应用程序时,没有太多与控制台窗口相关的事件处理程序,但我发现可以使用System.Console.CancelKeyPress中断正在进行的事件进程 假设以下程序: class Program { static void Main(string[] args) { Console.ForegroundColor = ConsoleColor.Blue; Console.CancelKeyPress += myHandler;

在编写控制台应用程序时,没有太多与控制台窗口相关的事件处理程序,但我发现可以使用
System.Console.CancelKeyPress
中断正在进行的事件进程

假设以下程序:

class Program
{
    static void Main(string[] args)
    {
        Console.ForegroundColor = ConsoleColor.Blue;
        Console.CancelKeyPress += myHandler;
        while (true)
        {
            Console.WriteLine("Hello World!");
            System.Threading.Thread.Sleep(1);
        }
    }



protected static void myHandler(object sender, ConsoleCancelEventArgs args)
    {
        args.Cancel = true;
        Console.WriteLine("  Cancel property: {0}", args.Cancel);
        Console.WriteLine("The read operation will resume...\n");
        Console.ReadLine();
    }
}
该程序在屏幕上无限打印“Hello World!”。中断是有效的,我假设它们共享一个线程,在按下Ctrl+C的瞬间,它进入处理程序方法。当它在屏幕上打印出有关cancel属性当前状态的信息时,事件中的Console.ReadLine()被完全忽略


这种行为是为了避免阻塞冲突,还是在触发此事件时存在读取输入的技巧?如果您真的想退出,请输入Y。

您可以按如下方式执行您希望执行的操作

 class Program
{
    private static bool running = true;
    private static bool stop = false;
    static void Main(string[] args)
    {
        Console.ForegroundColor = ConsoleColor.Blue;
        Console.CancelKeyPress += myHandler;
        while (!stop)
        {
                if (running)
                {
                    Console.WriteLine("Hello World!");                      
                } 
            System.Threading.Thread.Sleep(1000);
        }

        Console.WriteLine("Exiting ...");
    }



    protected static void myHandler(object sender, ConsoleCancelEventArgs args)
    {
        args.Cancel = true;
        running = false;
        Console.WriteLine("Do you wish to resume... Y/N \n");
        var resume = Console.ReadLine();

        if (resume == "Y")
        {
            running = true;
        }
        else
        {
            stop = true;
        }
    }
}

我怀疑事件处理程序正在控制台窗口主线程的不同上下文中运行。我以前没有在控制台窗口中真正使用过事件,但在WinForms中,GUI将在其自己的上下文线程上运行。

您可以按如下所示执行您希望执行的操作

 class Program
{
    private static bool running = true;
    private static bool stop = false;
    static void Main(string[] args)
    {
        Console.ForegroundColor = ConsoleColor.Blue;
        Console.CancelKeyPress += myHandler;
        while (!stop)
        {
                if (running)
                {
                    Console.WriteLine("Hello World!");                      
                } 
            System.Threading.Thread.Sleep(1000);
        }

        Console.WriteLine("Exiting ...");
    }



    protected static void myHandler(object sender, ConsoleCancelEventArgs args)
    {
        args.Cancel = true;
        running = false;
        Console.WriteLine("Do you wish to resume... Y/N \n");
        var resume = Console.ReadLine();

        if (resume == "Y")
        {
            running = true;
        }
        else
        {
            stop = true;
        }
    }
}

我怀疑事件处理程序正在控制台窗口主线程的不同上下文中运行。我以前没有在控制台窗口中真正使用过事件,但在WinForms中,GUI将在其自己的上下文线程上运行。

取消事件处理程序确实在另一个线程上运行(通过打印线程id来验证这一点)

运行事件的主线程和次线程不“共享线程”,但会将控制台输出用作共享资源

事件中的读取行不会被忽略。尽管“main”线程确实继续编写“helloworld”,但如果按enter键,事件处理程序将有效地读取您输入的输入

如果希望主线程“暂停”向控制台的写入,则必须找到一种机制来完成这一任务

下面是一个非常简单的实现:

    private static bool paused;
    static void Main(string[] args)
    {
        Console.WriteLine(Thread.CurrentThread.ManagedThreadId);

        Console.ForegroundColor = ConsoleColor.Blue;
        Console.CancelKeyPress += myHandler;
        while (true)
        {
            if (!paused)
                Console.WriteLine("Hello World!");
            System.Threading.Thread.Sleep(1000);
        }
    }

    protected static void myHandler(object sender, ConsoleCancelEventArgs args)
    {
        paused = true;
        Console.WriteLine("Do you want to exit?");
        Console.WriteLine(Thread.CurrentThread.ManagedThreadId);
        var answer = Console.ReadLine();
        args.Cancel = answer != "y";
        paused = false;
    }

cancel事件处理程序确实在另一个线程上运行(通过打印线程id来验证这一点)

运行事件的主线程和次线程不“共享线程”,但会将控制台输出用作共享资源

事件中的读取行不会被忽略。尽管“main”线程确实继续编写“helloworld”,但如果按enter键,事件处理程序将有效地读取您输入的输入

如果希望主线程“暂停”向控制台的写入,则必须找到一种机制来完成这一任务

下面是一个非常简单的实现:

    private static bool paused;
    static void Main(string[] args)
    {
        Console.WriteLine(Thread.CurrentThread.ManagedThreadId);

        Console.ForegroundColor = ConsoleColor.Blue;
        Console.CancelKeyPress += myHandler;
        while (true)
        {
            if (!paused)
                Console.WriteLine("Hello World!");
            System.Threading.Thread.Sleep(1000);
        }
    }

    protected static void myHandler(object sender, ConsoleCancelEventArgs args)
    {
        paused = true;
        Console.WriteLine("Do you want to exit?");
        Console.WriteLine(Thread.CurrentThread.ManagedThreadId);
        var answer = Console.ReadLine();
        args.Cancel = answer != "y";
        paused = false;
    }

谢谢你的解释,这确实澄清了它为什么是这样。谢谢你的解释,这确实澄清了它为什么是这样。