我正在用Ruby / Tk编写程序。有一次,我正在执行一项需要一些时间的任务,我想展示一些反馈。我用线程完成了这个。我是这个整个线程的新手,当我完成线程时,我不知道如何回到非线程世界。
让我用一个例子来说明。
legitCreds = true
doneValidate = false
# (A) Thread with time-consuming call
validator = Thread.new do
# THIS CALL TAKES 5-10 seconds
legitCreds = checkDoorsCreds(session, ValidateTimeout)
# indicate when this call is done
mutex.synchronize do
doneValidate = true
end
end
# (B) Thread with GUI feedback for user
timeElapsed = 0
textVisible = false
progress = Thread.new do
if ! doneValidate
loop do
sleep 0.5
timeElapsed += 0.5
mutex.synchronize do
if ValidateTimeout - timeElapsed <= 0 || doneValidate
@SI['statMessL'].text = ""
Thread.kill(progress)
end
end
if textVisible
@SI['statMessL'].text = ""
textVisible = false
else
@SI['statMessL'].text = "Timeout in #{(ValidateTimeout - timeElapsed).round} seconds..."
textVisible = true
end
end
end
end
# (C) Should only run after A and B are done.
if legitCreds
File.open(PathToUserNames, 'w') { |file| file.write(@SI['unameTB'].get) }
# Go to next state!
end
所以问题在于,正如上面编码的那样,(C)在完成(A)和(B)之前运行,这是无用的,因为 legitCreds 是由线程A设置的。
我想在(C)
之前加上以下代码validator.join
progress.join
但这会冻结GUI,我也不想这样做。
我还考虑将(C)的内容放在(A)的末尾(但仍然在验证器线程内。这让我得到了正确的行为,但它似乎错了,因为那时候我的程序的其余部分看起来将在验证器线程中运行。
总之,我希望在(A)和(B)之后运行(C)而不冻结GUI,而(A)和(B)工作。
我该怎么做?
另外,如果你看到任何其他no-nos,请告诉我。正如我所说,我是新手,我想养成良好的习惯。
谢谢,
Grasswistle
答案 0 :(得分:0)
您写道:
我还想过把(C)的内容放在(A)的末尾(但是 仍在验证程序线程内。这让我行为正确, 但它似乎是错误的,因为我的程序的其余部分看起来像它 将在验证程序线程中运行。
我不熟悉Tk,但据我所知的GUI应用程序,你的程序不会从另一个线程开始工作 - (C)只会改变应用程序的状态和GUI事件将继续从GUI线程处理...
所以(C)可以附加到(A)或(B)(关注点的分离可能有利于(B)而不是(A)),并且你的申请应该顺利地继续......