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
printed
0
的值。但是线程不会更改第一次输入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