From: Bill Kelly Date: 2006-01-09T02:48:45+09:00 Subject: Re: Newbie question about threads and gets From: "Jacek Olszak" > > I've a simple question - how can I write an application with two > threads, where first thread reads the user input. I want both threads to > run SIMULTANEOUSLY. > So .. here is my code: > > a=Thread.new do > $stdin.gets > end > > b=Thread.new do > 5.times do > print "b" > $stdout.flush > Thread.pass > end > end > > a.join > b.join > > Unfortunelty "gets" block my whole application - the "b" thread waits > until user writes something to the stdin. But I want the b thread not > wait and run at the same time. This tends to be a problem with Windows ruby. It seems unlikely to be resolved until Ruby gets native threads (on the horizon with YARV.) Here's how I've worked around it. If anyone knows a better way, please share: if RUBY_PLATFORM =~ /win32/ require 'Win32API' $win32_console_kbhit = Win32API.new("msvcrt", "_kbhit", [], 'I') def console_input_ready? $win32_console_kbhit.call != 0 end def nonblocking_stdin_gets sleep(0.1) until console_input_ready? $stdin.gets # don't bother to use getc, it also blocks until user hits end else def nonblocking_stdin_gets $stdin.gets # it just works, on unix end end So you can use nonblocking_stdin_gets in place of $stdin.gets. It's an imperfect solution, though. It will be nonblocking _until_ the user starts typing. Then it will block until they hit . (Note, I've tried doing it character-by-character, with $stdin.getc or $stdin.sysread(1), but it still blocks until the user hits .) There's probably a way to put the windows console into unbuffered mode, which would improve this hack (so we could use $stdin.getc in conjunction with console_input_ready?.) Anyway, hope this helps . . . Regards, Bill