【问题标题】:Thread ignoring first input when using getch使用getch时线程忽略第一个输入
【发布时间】:2018-03-12 09:13:19
【问题描述】:
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

当我运行代码时,我得到了flag 的值,它应该打印0。但是线程不会更改我点击的 first Enter 上的flag 的值。不过,第二次按 Enter 会将标志更改为 1。该线程正常工作,在进一步 Enter 命中时切换flag 的值。为什么会这样?我做错了什么?

问题似乎只出在getch 当我使用gets 代替getch 时,问题就消失了。但我不能使用gets,因为我希望用户点击一个键而不需要在键后按 Enter 来输入。 例如,flag 不应该在用户输入 a 而不是 Enter 时改变,所以我使用getch 来确保在单次键盘敲击后给出输入.

here 描述了一个类似的问题,但它不是重复的。

编辑 1: 问题似乎出在getch 而不是检查过的问题。

flag = 0

t2 =Thread.new do
  puts flag

  loop do
    temp = STDIN.getch
    flag = (flag+1)%2
    puts flag
  end

end
t2.join

即使删除 if 语句,第一个 Enter 无论如何都会被忽略,但其他字符似乎第一次响应。只有当我点击 Enter 时才会出现问题。它不计算我点击的第一个 Enter

ruby 2.3.3p222 (2016-11-21 revision 56859) [x64-mingw32]

【问题讨论】:

    标签: ruby multithreading stdin getch


    【解决方案1】:

    我在 Windows 机器上尝试了您的代码,并且能够重现问题。正如您正确猜测的那样,它与线程无关,而与getch 的工作方式无关(在 Windows 上)。 如果你在你的循环中添加一个p temp.inspect,你会发现第一个'\n'并没有被吞下,而是它以某种方式被“阻止”了。如果您按 Enter 和另一个键,最好的方式是看到这个。您会看到检查是“逐一”的。

    这里讨论了关于这个问题的一个很好的解释: https://www.rubytapas.com/2016/12/14/ruby-code-on-windows/

    有了这些信息,一个简单的解决方案(还有一个额外的好处是可以在 Linux 上运行,不确定 Mac)是:

    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
    

    注意事项: 诚然,我并没有完全理解它的工作方式。我原以为 Enter 会在 binmode 中导致“\r\n”序列,但我只看到“\r”。不确定“\n”会发生什么,但它似乎以这种方式可靠地工作。 另请注意,在当前版本中,无法使用 Ctrl+C 终止程序。您必须为此添加支票。

    【讨论】:

    • 真的很有帮助。 ty
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-10-23
    • 1970-01-01
    • 1970-01-01
    • 2014-08-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多