c# - 从 stdin 非阻塞读取一个字节

标签 c# mono stdin nonblocking

我想通过以下方式从 C# mono 进程的标准输入(标准输入)读取一个字节(或字符):

  • 如果已经有字节可用于从标准输入读取,则返回第一个
  • 如果没有可从标准输入读取的字节,则不等待或阻塞继续
  • 如果有线程或异步,它应该是简洁且可证明正确的按需获取单个字节的插入式解决方案
  • stdin 可以是管道或文件,因此 Console.KeyAvailable 不会

谢谢。

最佳答案

如果您的平台有 System.Collections.Concurrent.BlockingCollection 的实现,这里有一个简单但不完全有效的方法:

class ConsoleReader {
  private readonly BlockingCollection<int> buffer = new BlockingCollection<int>(1);
  private readonly Thread readThread;
  public ConsoleReader() {
    readThread = new Thread(() => {
      if (Console.IsInputRedirected) {
        int i;
        do {
          i = Console.Read();
          buffer.Add(i);
        } while (i != -1);
      } else {
        while (true) { 
          var consoleKeyInfo = Console.ReadKey(true);
          if (consoleKeyInfo.KeyChar == 0) continue;  // ignore dead keys
          buffer.Add(consoleKeyInfo.KeyChar);
        }
      }
    });
  }

  public void Start() {
    readThread.Start();
  }

  public int? Next {
    get {
      int result;
      return buffer.TryTake(out result, 0) ? result : default(int?);
    }
  }
}

免责声明:此答案实际上并未在 Mono 上进行过测试,只是在完整的 .NET 平台上进行了短暂测试。 您可以使用 Task 而不是 Thread、适当的取消等来增加它的趣味性,但这不会改变显式等待同步操作的中央效率低下(这Console.ReadConsole.ReadKey 都是)。 .NET 本身不提供可移植异步控制台 I/O。自己跨平台实现(使用操作系统功能)是可能的,但绝对不是一件容易的事。

关于c# - 从 stdin 非阻塞读取一个字节,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44989149/

相关文章:

mono - 在 Centos 上编译和安装 Mono - 无法通过 'make'

powershell - 在 Windows PowerShell 中重定向标准输入\输出

.net - 如何获得更多 RDBMS 功能但仍使用 SQLite?

c# - 等待 RunOnUIThread 完成并继续执行剩余的任务

java - 标准输入 Java 输入

python - 通过 echo 管道将 python 变量(字符串)传递给 bash 命令

c# - IEqualityComparer 使用 Except, Intersect

c# - 如何将 public void PassValue(string) 中的文本调用到 private void Form1_Load()

C# Wcf POST 值

c# - 如何制作 Optional 1 :1 Relationship in EF6 with the same Entity Type on both sides?