Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如果我在单独的Ruby线程中进行密集计算,为什么Ruby1.9GUI会挂起?_Ruby_Multithreading_Ruby 1.9 - Fatal编程技术网

如果我在单独的Ruby线程中进行密集计算,为什么Ruby1.9GUI会挂起?

如果我在单独的Ruby线程中进行密集计算,为什么Ruby1.9GUI会挂起?,ruby,multithreading,ruby-1.9,Ruby,Multithreading,Ruby 1.9,Ruby 1.9应该有本机线程,如果一些线程输入本机代码(如GUI工具包主循环或某些Ruby库的C实现),GIL应该提升 但如果我开始遵循在主线程中显示GUI的简单代码示例,并在单独的线程中进行一些基本的数学运算,GUI将挂起,请尝试调整窗口大小,以便自己查看。我已经使用不同的GUI工具包Qt(qtbindings gem)进行了检查——它的行为完全相同。在Windows7和OSX10.7上使用Ruby1.9.3-p0进行测试 require 'tk' require 'thread' Thre

Ruby 1.9应该有本机线程,如果一些线程输入本机代码(如GUI工具包主循环或某些Ruby库的C实现),GIL应该提升

但如果我开始遵循在主线程中显示GUI的简单代码示例,并在单独的线程中进行一些基本的数学运算,GUI将挂起,请尝试调整窗口大小,以便自己查看。我已经使用不同的GUI工具包Qt(qtbindings gem)进行了检查——它的行为完全相同。在Windows7和OSX10.7上使用Ruby1.9.3-p0进行测试

require 'tk'
require 'thread'
Thread.new { loop { a = 1 } }
TkRoot.new.mainloop()
Python中的相同代码在没有任何GUI挂起的情况下运行良好:

from Tkinter import *
from threading import *
class WorkThread( Thread ) :
  def run( self ) :
    while True :
      a = 1
WorkThread().start()
Tk().mainloop()
我做错了什么

更新

看起来Ubuntu linux上哪里没有这样的问题,所以我的问题主要是关于Windows和OSX

更新

有人指出OSX上哪里没有这样的问题。因此,我制定了一个分步指南,以隔离和重现一个问题:

  • 通过“恢复”功能安装OSX 10.7 Lion。我使用我们的测试部门MB139RS/A mac mini进行测试
  • 安装所有更新。系统将如下所示:
  • 从activestate.com安装最新的ActiveTcl,在我的例子中,它是针对OSX的ActiveTcl 8.5.11
  • 下载并解压缩最新的Ruby源代码。就我而言,它是Ruby 1.9.3-p125。编译并安装替换系统Ruby(下面的命令)。最终,您将获得具有内置Tk支持的最新ruby:
  • 使用示例中的代码创建一个
    test.rb
    文件并运行它。尝试调整窗口大小-您将看到严重的延迟。从代码中删除线程,开始并尝试调整窗口大小-延迟消失。我录了一段
  • Ruby编译命令:

    ./configure --with-arch=x86_64,i386 --enable-pthread --enable-shared --with-gcc=clang --prefix=/usr
    make
    sudo make install
    

    你的线程块将使用100%个CPU,这是不可能的任何真正的代码会吃那么多(如果你正在做真正的密集计算,你应该考虑另一种语言),也许尝试添加一些暂停:

    require 'tk'
    require 'thread'
    require 'rexml/document'
    Thread.new { loop { sleep 0.1; a = 1 } }
    TkRoot.new.mainloop()
    
    你的代码在Mac OS X 10.7和1.9.3 btw上运行良好


    虽然我非常喜欢ruby,但在我看来,当前的gui库状态非常糟糕,因此我避免使用它。

    这种挂起可能是由工具箱中ruby绑定的C代码造成的。正如您所知,ruby线程有一个:the。TKC线程和纯Ruby线程之间的混合似乎并不顺利

    对于类似的情况,您可以尝试在
    要求“tk”之前添加这些行。

    module TkCore 
      RUN_EVENTLOOP_ON_MAIN_THREAD = true
    end
    
    图形工具包需要一个主线程来刷新图形元素。如果您的线程处于密集计算中,那么您的线程会大量请求锁,因此会干扰toolkit的线程

    如果愿意,您可以避免使用睡眠技巧。在Ruby 1.9中,可以使用或。根据oldmoe的说法,纤维

    如果可以使用,还可以保留Ruby线程。这就是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
    
    rd,wr=IO.pipe
    如果叉子
    关闭
    放入“父对象得到:”
    道口
    等等
    其他的
    道口
    将“发送消息给家长”
    写“嗨,爸爸”
    关闭
    结束
    
    fork
    调用启动两个进程。在
    内部,如果
    ,则您处于父进程中。在
    else
    中,您是孩子。对
    Process.wait的调用关闭子进程。
    例如,您可以尝试在主gui循环中读取您的子对象,只有在收到所有数据后才关闭并等待子对象


    编辑:如果选择在Windows下使用fork(),则需要执行以下操作。

    根据平台的不同,您可以设置线程的优先级:

    require 'tk'
    require 'thread'
    require 'rexml/document'
    t1 = Thread.new { loop { a = 1 } }
    t1.priority = 0
    t2 = TkRoot.new.mainloop()
    t2.priority = 100
    

    如果你认真地使用多线程,你可能想考虑使用JRuBuy。它使用Java线程实现Ruby线程,使您能够访问Java并发库、工具和经过良好测试的代码

    在大多数情况下,您只需将ruby命令替换为jruby命令

    这里有一个开始。

    不确定,但Ruby 1.9是否仍然拥有GIL(全局解释器锁)?这完全可以解释你的问题…@Romain GIL如何解释我的问题?Python有相同的GIL,没有问题。GIL意味着只有一个线程可以同时运行ruby代码,所以如果您的后台计算可以使用它,您的UI代码就不能使用。@Romain Python有相同的GIL,没有这样的问题。Ruby调度程序将在一段时间后停止后台线程(大约100条Ruby指令?),并给其他线程一些CPU时间。通过快速切换,Ruby将实现近乎并行的执行。例如,如果您启动两个都运行ruby代码的ruby线程,ruby将在线程之间快速切换,因此对您来说,它们将像并行一样执行。这很有意义。不管怎样,你都看不出你的代码有什么问题。由于它不能是GIL…在python代码中,它也有100%的CPU负载,但没有GUI冻结。多线程处理就是执行多个线程,而不管每个线程的CPU使用情况如何。例如,如果您使用相同的无限循环启动两个ruby线程,那么这两个线程将完全并行工作,每个线程使用50%的CPU。那么为什么GUI不是这样工作的呢?关于OSX 10.7-只需使用resize而不是window move,OSX将无延迟地移动窗口,即使GUI没有响应,这是操作系统的特性。我认为发生的事情是GUI主循环是在C中的,因为您的ruby代码占用了大量cpu。应用程序在ruby端比在C端花费更多的时间。我从来没有用过tk,但这种现象应该接近事实。(我不知道它在python上是如何工作的,也不知道为什么它在ruby上的工作方式不同,也许库的架构不同)AFAIK ruby和python使用相同的tcl/tk库。不管怎样,我所知道的任何工具包的情况都是一样的:Tk、Qt、GTK等等。所有这些在python中都可以正常工作,在Ruby中GUI严重滞后。我的问题是“为什么会这样”:。我不是说tk库本身,而是说wra