如何检查 NSFileHandle 是否有可用数据?
我正在使用 NSTask,配置了 3 个 NSPipe,并且想要从 standardOutput 和 standardError 中读取。我在 while 内执行此操作 - 第一个用于标准输出,第二个用于标准错误。 我不能使用 readInBackgroundAndNotify 和 waitForDataInBackgroundAndNotify,因为我的代码已经在单独的线程中运行,并且我不想在那里运行 NSRunLoop 并分离新的后台线程...但是读取两者 - stdout 和 stderr 会导致在没有可用数据时出现一些挂起数据存在于这些通道之一中。
所以我使用这段代码:
@implementation NSFileHandle (isReadableAddon)
- (BOOL)isReadable
{
int fd = [self fileDescriptor];
fd_set fdset;
struct timeval tmout = { 0, 0 }; // return immediately
FD_ZERO(&fdset);
FD_SET(fd, &fdset);
if (select(fd + 1, &fdset, NULL, NULL, &tmout) <= 0)
return NO;
return FD_ISSET(fd, &fdset);
}
@end
但是,当 isReadable 返回 YES 并且我调用 [fileHandle availableData] 时,我的线程仍然阻塞。 为什么? 我期望当 isReadable 返回 YES 时调用 availableData 方法而不阻塞。
I'm working with NSTask, configured with 3 NSPipe, and want to read from standardOutput and standardError. I do it inside while - 1st for stdout, next for stderr.
I can't use readInBackgroundAndNotify and waitForDataInBackgroundAndNotify, since my code is already running in separate thread, and I don't want run NSRunLoop there and detach new background threads... But reading both - stdout and stderr cause some hang on availableData when no data present in one of these channels.
So I use this code:
@implementation NSFileHandle (isReadableAddon)
- (BOOL)isReadable
{
int fd = [self fileDescriptor];
fd_set fdset;
struct timeval tmout = { 0, 0 }; // return immediately
FD_ZERO(&fdset);
FD_SET(fd, &fdset);
if (select(fd + 1, &fdset, NULL, NULL, &tmout) <= 0)
return NO;
return FD_ISSET(fd, &fdset);
}
@end
However, when isReadable returns YES and I call [fileHandle availableData], my thread still blocks.
Why?
I expected call availableData method without blocking when isReadable returned YES.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我也更喜欢使用
select
但如果您想使用非阻塞,请阅读这里的要点,这对我有用。Swift 4
查看 Linux select手册页:
I also prefer using
select
but incase you want to work with a non-blocking read here's a gist that works for me.Swift 4
see the Linux select man page:
Swift 4 版本(适用于 macOS):
Swift 4 version (for macOS):