如果我不使用线程,我通常可以在端口声明中使用@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
每次启动窗口时,您都在启动一个全新的应用程序,因此该新应用程序中的变量对于其他应用程序是未知的,而第一个应用程序中的变量,即触发窗口方法的变量对于新应用程序是未知的!幸运的是,每个 Shoes 应用程序中都有一个可用的所有者方法,在您的情况下,在新应用程序中调用的所有者会为您提供对第一个应用程序的引用,即拥有新应用程序的应用程序!一种做你想做的事的方法(线程或不线程):
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 方法,该方法会返回一个包含所有打开的应用程序的数组。
如果这是 Shoes 4,那么线程很可能无法访问 UI(只有主线程可以访问 UI)。您可以尝试事先提取值,然后将其传递给作为参数编写:
def write(port)
#...
end
port = @which_port.text.to_i
@th1 = Thread.new { write(port) }