From: Paul Brannan Date: 2004-08-30T23:07:08+09:00 Subject: Re: Blocking Problem On Sun, Aug 29, 2004 at 07:28:59AM +0900, Zachary P. Landau wrote: > The problem is, I can't avoid blocking. There is a GTK application, and > then a separate thread that tries to read barcodes and whenever it finds > one, it tells the GTK app. > > So my code looks like this: > > Thread.new do > File.open(CUECAT_DEV, File::RDONLY | File::NONBLOCK) do |cuecat| > loop do > id, barcode_type, barcode = cuecat.gets.split(/,/) > # do stuff with the barcode > end > end > end Some notes: 1. IIRC, #gets always has the potential to block, even if you are in non-blocking mode (as for why it doesn't relinquish control back to the GUI thread, I don't know; that's a totally different question) 2. Gtk has a method for dealing with long-running IO operations; essentially what you want to do is register it with Gtk using Gtk.input_add(io, Gdk::INPUT_READ) { ... } (I'm still using Gtk 1.2; this may be a little different in 2.x?) 3. This will give you a callback whenever data are available, but this doesn't mean an entire line is available or that multiple lines are not available. So for that I use: data = io.sysread(512) @data << data while line = @data.slice!(/.*\n/) do line.strip! handle_line(line) end To put it together, instead of starting a new thread, you can instead use: cuecat = File.open(CUECAT_DEV, File::RDONLY) Gtk.input_add(io, Gdk::INPUT_READ) do data = io.sysread(512) @data << data while line = @data.slice!(/.*\n/) do id, barcode_type, barcode = cuecat.gets.split(/,/) # do stuff with the barcode end end I think this will make your life much simpler (especially since you don't have all those thread-safety issues to worry about). Paul