Это зависание может быть вызвано кодом C привязок Ruby в Toolkit.Как вы знаете, рубиновые потоки имеют глобальную блокировку : GIL .Кажется, что смешивание между потоком Ruby bindings , потоком Tk C и потоком Pure Ruby идет не очень хорошо.вы можете попытаться добавить эти строки до того, как require 'tk'
:
module TkCore
RUN_EVENTLOOP_ON_MAIN_THREAD = true
end
Графическому инструментарию необходим основной поток для обновления графических элементов.Если ваш поток требует интенсивных вычислений, он интенсивно запрашивает блокировку и поэтому вмешивается в поток инструментария.
Вы можете избежать использования трюка sleep , если хотите.В Ruby 1.9 вы можете использовать Fiber , Revactor или EventMachine .Согласно oldmoe, Fibers кажется довольно быстрым .
Вы также можете сохранить нити Ruby, если можете использовать IO.pipe .Вот так были реализованы параллельные тесты в ruby 1.9.3.Кажется, это хороший способ обойти потоки Ruby и ограничения GIL.
Документация показывает пример использования:
rd, wr = IO.pipe
if fork
wr.close
puts "Parent got: <#{rd.read}>"
rd.close
Process.wait
else
rd.close
puts "Sending message to parent"
wr.write "Hi Dad"
wr.close
end
Вызов fork
инициирует два процесса.Внутри if
вы находитесь в родительском процессе.Внутри else
, вы в ребенке.Вызов Process.wait
закрывает дочерний процесс.Например, вы можете попытаться читать от своего ребенка в основном цикле графического интерфейса пользователя и закрывать и ждать ребенка только после получения всех данных.
РЕДАКТИРОВАТЬ : Вы 'Вам понадобится win32-process , если вы решите использовать fork () под Windows.