我希望能够取消一个os.stdin读使用上下文,这是不可能的。通常,关闭文件句柄来完成取消操作,但我不想关闭os.stdin
可能的解决办法是:
- 是否可以确定标准输入读取是否会阻塞?
- 线程可以像pthreads那样终止吗?
- 是否应将os.stdin转发到另一个可以关闭的文件句柄?
这是我得到的,丑陋的是scannerThread在上下文取消时仍然运行:
// Keystrokes emits keystroke events
// on g0.Context() shutdown, scannerThread is left running until the next newline
// the lines channel is never closed
func Keystrokes(lines chan<- string, g0 parl.Go) {
var err error
defer g0.Done(err)
defer parl.Recover(parl.Annotation(), &err, parl.NoOnError)
// stdio.Scan cannot be terminated, so let that thread terminate whenever
var scanLines parl.NBChan[string]
go scannerThread(scanLines.Send, g0.Context())
// consume scannerThread output
scannerCh := scanLines.Ch()
done := g0.Context().Done()
for {
select {
case line := <-scannerCh:
lines <- line
case <-done:
return // canceled by context exit
}
}
}
// scannerThread reads from os.Stdin and therefore cannot be cancelled.
// send is a non-blocking send function.
// ctx indicates shutdown effective on next os.Stdin newline.
func scannerThread(send func(string), ctx context.Context) {
var err error
defer parl.Recover(parl.Annotation(), &err, parl.Infallible)
scanner := bufio.NewScanner(os.Stdin)
for scanner.Scan() { // scanner is typically stuck here
if ctx.Err() != nil {
return // terminated via context
}
send(scanner.Text())
}
// scanner had error
err = scanner.Err()
}
2条答案
按热度按时间uurv41yg1#
答案是读os.Stdin非阻塞,适用于Linux macOS
我记得,Stdin有一个阻止关闭它的块
非阻塞的os.Stdin.Read()在一个完整的行可用时返回字节,否则返回n==
以下是如何设置非阻塞:
也可以读取非阻塞状态:
ffscu2ro2#
没有办法做到这一点开箱即用。您需要依靠利用OS功能的特殊实现。
有一个图书馆显然可以做到这一点:https://github.com/muesli/cancelreader
下面是它的工作原理:
它以一种相对跨平台的方式完成了你所需要的一切。