Ruby 线程在使用getch时忽略第一个输入
当我运行代码时,我得到了Ruby 线程在使用getch时忽略第一个输入,ruby,multithreading,stdin,getch,Ruby,Multithreading,Stdin,Getch,当我运行代码时,我得到了flagprinted0的值。但是线程不会更改第一次输入I hit上的标志的值。点击第二次输入将标志更改为1。在进一步输入命中时,线程正常地切换标志的值。为什么会这样?我做错了什么 问题似乎只存在于getch 当我使用gets代替getch时,问题就消失了。但是我不能使用get,因为我希望用户只按一个键,而不需要在键后按Enter键进行输入。 例如,flag不应该在用户输入a而不是Enter时更改,因此我使用了getch来确保输入是在一次键盘点击后给出的 描述了一个类似的
flag
printed0
的值。但是线程不会更改第一次输入I hit上的标志
的值。点击第二次输入将标志更改为1
。在进一步输入命中时,线程正常地切换标志的值。为什么会这样?我做错了什么
问题似乎只存在于getch
当我使用gets
代替getch
时,问题就消失了。但是我不能使用get
,因为我希望用户只按一个键,而不需要在键后按Enter键进行输入。
例如,flag
不应该在用户输入a而不是Enter时更改,因此我使用了getch
来确保输入是在一次键盘点击后给出的
描述了一个类似的问题,但它不是重复的
编辑1:
问题似乎出在getch
上,而不是检查“做什么”
require 'rubygems'
require 'mechanize'
require 'io/console'
flag = 0
t2 =Thread.new do
puts flag
loop do
temp = STDIN.getch
if temp=="\n"
flag = (flag+1)%2
puts flag
end
end
end
# => Some foreground code
t2.join
即使在删除if语句之后,第一个Enter也会被忽略,不管是什么,但是其他字符似乎会第一次响应。只有当我按下回车键时,问题才会出现。这不算我第一次进入
我在Windows计算机上尝试了您的代码,并能够重新创建问题。正如您正确猜测的,它与线程无关,与getch
如何工作(在Windows上)无关。
如果将p temp.inspect
添加到循环中,您将看到,与其说第一个'\n'被吞下,不如说它被某种方式“抑制”。如果您交替按Enter键和其他键,则最好查看此信息。您将看到检查“一次关闭”
这里讨论了关于该问题的一个很好的解释:
有了这些信息,一个简单的解决方案(也可以在Linux上运行,但不确定Mac)是:
注:
诚然,我并不完全理解它的工作方式。我原以为Enter会在binmode中导致一个“\r\n”序列,但我只看到“\r”。不确定“\n”会发生什么情况,但它似乎以这种方式可靠地工作。
另外请注意,在当前版本中,不能使用Ctrl+C终止程序。您必须为此添加一个检查。真的很有帮助。泰
flag = 0
t2 =Thread.new do
puts flag
loop do
temp = STDIN.getch
flag = (flag+1)%2
puts flag
end
end
t2.join
ruby 2.3.3p222 (2016-11-21 revision 56859) [x64-mingw32]
require 'rubygems'
require 'mechanize'
require 'io/console'
STDIN.binmode #this line added to prevent line-end translation
flag = 0
t2 =Thread.new do
puts flag
loop do
temp = STDIN.getch
if temp=="\r" # note: changed from LF to CR
flag = (flag+1)%2
puts flag
end
end
end
# => Some foreground code
t2.join