我想通过以下方式从 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.Read
和 Console.ReadKey
都是)。 .NET 本身不提供可移植异步控制台 I/O。自己跨平台实现(使用操作系统功能)是可能的,但绝对不是一件容易的事。
关于c# - 从 stdin 非阻塞读取一个字节,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44989149/