从 stdin 非阻塞读取一个字节
Non-blocking read of a byte from stdin
我想通过以下方式从 C# mono 进程的标准输入(标准输入)读取一个字节(或字符):
- 如果已经有字节可供从标准输入读取,return第一个
- 如果没有可从标准输入读取的字节,则不等待或阻塞继续
- 如果有线程或异步,它应该是简洁且可证明正确的按需获取单个字节的插入式解决方案
- 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。自己跨平台实施(使用 OS 功能)是可能的,但绝对不平凡。
我想通过以下方式从 C# mono 进程的标准输入(标准输入)读取一个字节(或字符):
- 如果已经有字节可供从标准输入读取,return第一个
- 如果没有可从标准输入读取的字节,则不等待或阻塞继续
- 如果有线程或异步,它应该是简洁且可证明正确的按需获取单个字节的插入式解决方案
- 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。自己跨平台实施(使用 OS 功能)是可能的,但绝对不平凡。