【问题标题】:c# incomplete Console.ReadKey() calls I don't want the user to completec#不完整的Console.ReadKey()调用我不希望用户完成
【发布时间】:2019-06-23 00:24:58
【问题描述】:

我正在学习套接字消息传递。我在一个while循环中打断了 Console.ReadKey() 并且很多调用最终都没有完成。我正在尝试找到一种方法来删除不完整的调用,而无需用户全部输入。

见过

while(Console.KeyAvailable){Console.ReadKey(true);}

但我有相反的问题,电话太多,按键次数不够。

How to add a Timeout to Console.ReadLine()? 这个问题把我带到了现在的位置,但它并没有解决我当前的问题。

using System;
using System.Threading;

class Program
{
    static void Main(string[] args)
    {
        DontLockOnCharGet bug = new DontLockOnCharGet();
        bug.Setup();
    }
}

public class DontLockOnCharGet
{
    public void Setup()
    {
        while (true) { DontLockCharGet(); }
    }

    public void DontLockCharGet()
    {
        while (true)
        {
            // used to interrupt the Console.ReadKey() function
            AutoResetEvent getInput = new AutoResetEvent(false);
            AutoResetEvent gotInput = new AutoResetEvent(false);

            // Console.ReadKey() assigns to input
            char input = ' ';

            //Lambda used to get rid of extra class
            Thread tom = new Thread(() =>
            {
                getInput.WaitOne(); // Waits for getInput.Set()

                //The problem with this is the read keys stacking up
                // causing the need for a lot of keystrokes
                input = Console.ReadKey().KeyChar;

                gotInput.Set();
            })
            {
                IsBackground = true
            };
            // Starts Lambda function
            tom.Start(); 

            // Allows thread to pass WaitOne() in Lambda
            getInput.Set(); 
            // Gives some milliseconds for before stopping Lambda exe
            gotInput.WaitOne(2000);

            if (input == 'S' || input == 's')
            {
                break;
            }
            // thinking I would put the solution here
            //...
        }
        //Do stuff if input is s || S
        Console.Write("end: ");
    }
}

我希望能够按's' || 'S',然后输入一条消息,但根据我等待的时间长短,我可能需要按住 's' 很长时间。

由于第一条评论,我遇到的解决方案。

using System;
using System.Threading;

/// <summary>
/// Problem fixed I don't know why
/// Probably not making a new function for each call
/// </summary>
class Program
{
    static void Main(string[] args)
    {
        DontLockOnCharGet bug = new DontLockOnCharGet();
        bug.Setup();
    }
}
public class DontLockOnCharGet
{
    public void Setup()
    {
        while (true) { DontLockCharGet(); }
    }

    public void DontLockCharGet()
    {
        while (true)
        {
            //Specifies time to wait for input
            char i = Reader.ReadKey(1000);
            if (i == 's' || i == 'S')
            {
                //Do stuff if input is s || S
                break;
            }
            Console.Write(i);
        }
        // Do stuff
        Console.Write("end: ");
    }
}

class Reader
{
    private static Thread inputThread;
    private static AutoResetEvent getInput, gotInput;
    private static char input;

    static Reader()
    {
        //Setup once
        getInput = new AutoResetEvent(false);
        gotInput = new AutoResetEvent(false);

        //inputThread = new Thread(reader);
        //inputThread.IsBackground = true;
        //inputThread.Start();
    }

    private static void reader()
    {
        //waits for .Set()
        getInput.WaitOne();
        input = '\0';
        input = Console.ReadKey().KeyChar;
        //Marks if input is gotten
        gotInput.Set();
    }

    // omit the parameter to read a line without a timeout
    public static char ReadKey(int timeOutMillisecs = Timeout.Infinite)
    {
        //Setup and start read thread
        inputThread = new Thread(reader)
        {
            IsBackground = true
        };
        inputThread.Start();
        //Allows thread to continue in reader()
        getInput.Set();
        //Wait for input or back out befor it is given
        bool success = gotInput.WaitOne(timeOutMillisecs);
        return input;
    }
}

此版本的代码按预期工作: 输入“S”,它会自动完成“发送:”

【问题讨论】:

  • 从复杂的代码状态中可以清楚地看出,无论您尝试做什么,都以错误的方式进行。但是......我真的不知道你想做什么。您的评论说“读取键堆积”,但我不知道这意味着什么。您发布的代码一次应该只发出一个 ReadKey() 调用,因为该方法会阻塞,直到有一个按键,并且因为您只有一个线程调用它。请修正您的帖子,使其准确地详细说明用户输入和操作是什么,以及准确地您要完成什么。
  • 谢谢@PeterDuniho 我很确定问题出在为每个循环的线程创建一个函数。

标签: c# timeout console.readkey


【解决方案1】:

问题出在new Thread(()=&gt; { ... }); 这是创建一个新函数而不仅仅是一个新函数调用。正在创建的函数应该像这样移动到一个单独的函数中

private void ReadKey(){
        // Waits for getInput.Set()
        getInput.WaitOne();

        //The problem with this is the read keys stacking up
        // causing the need for a lot of keystrokes
        input = Console.ReadKey().KeyChar;

        gotInput.Set();
}

在课堂内。

制作这些

AutoResetEvent getInput, gotInput;
char input;

类变量并在Setup(){...}中初始化它们

最后调用Thread tom = new Thread(ReadKey);,当前正在创建新函数。

注意:此答案不适用于最佳实践,但可以让原型工作。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-05-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-03-27
    • 2016-01-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多