Ruby 鞋子 GUI 设置端口不适用于线程

Ruby Shoes GUI set port don't work with thread

如果我不使用线程,我可以在端口声明中正常使用@which_port.text.to_i。如果我使用线程,看起来这条语句 @which_port.text.to_i 不起作用。我只能手动写端口,例如6000 然后我的程序运行良好。我必须使用线程,否则我的程序会冻结。尽管使用线程,有什么方法可以使用 @which_port.text.to_i

require 'socket'
require 'thread'

Shoes.app do

def write
    @t = TCPSocket.new("xx.xx.xx.xx", @which_port.text.to_i)
    loop do
        msg = @t.recv(4096)
        @pa1.text = @pa1.text + msg
    end
end 

@btn = button("button", width: 80, height: 50) do
    window(left: 300, top: 300) do
    @pa1 = para ""
    @th1 = Thread.new { write }
   end
end

@e_ln = edit_line(width: 320, height: 25, margin_top: 5)

@which_port = list_box :items => ["5000", "6000", "7000"],
    :width => 120,
    :choose => "5000" do |list| 
    end
end
end

如果这是鞋子 4,那么线程很可能无法访问 UI(只有主线程可以访问 UI)。您可以尝试预先提取值,然后将其作为参数传递给 write:

def write(port)
  #...
end

port = @which_port.text.to_i
@th1 = Thread.new { write(port) }

每次您启动 window 您都在启动一个全新的应用程序,因此新应用程序中的变量对于其他应用程序以及第一个应用程序中的变量是未知的应用程序,触发 window 方法的应用程序对于新应用程序是未知的!幸运的是,每个 Shoes 应用程序都有一个 owner 方法,在您的情况下,在新应用程序内部调用的 owner 会为您提供对第一个应用程序的引用,即拥有新应用程序的应用程序! 一种做你想做的事情的方法(线程与否):

Shoes.app title: "Main Shoes app" do
    def write(paragr)
        msg = "#{self.inspect} === #{@which_port.text}"
        paragr.text = paragr.text + msg
    end

    @btn = button("button", width: 80, height: 50) do
        window(left: 300, top: 300, title: "Another Shoes app") do
            @pa1 = para ""
            Thread.new { owner.write(@pa1) }
        end
    end


    @which_port = list_box :items => ["5000", "6000", "7000"],
                           :width => 120,
                           :choose => "5000" do |list|
    end
end

您还可以研究 Shoes.APPS 方法,该方法返回一个包含所有打开的应用程序的数组。