目测我的标题取错了,但是我实在不知道怎么用术语描述。
问题大概是这样的:在用 python 写一个五子棋 AI,那么就需要玩家下一步,电脑思考,电脑下一步。现在电脑思考大概需要 2 秒的时间。
代码大概是这样的:
que_game2ui = Queue(maxsize=2)
que_ui2game = Queue(maxsize=2)
class GUI:
def __init__(self, ui):
# self.bg = ui 的一个 canvas
pass
def on_click(self, event):
col = (event.x + GUICONF["half_gap"]) // GUICONF["gap"] - 1
row = (event.y + GUICONF["half_gap"]) // GUICONF["gap"] - 1
que_ui2game.put({
"option": "move",
"loc": (row, col),
})
def queue_handler(self):
try:
task = que_game2ui.get(block=False)
# 更新界面
self.bg.after(10, self.queue_handler)
except queue.Empty:
self.bg.after(10, self.queue_handler)
class GAME(Gomokuy):
def __init__(self, _gui)
# Gomokuy 是自己写的 AI 的类
# self.gui = _gui
pass
def moving(self, row, col):
if self.winner:
print("游戏结束")
return
ret = self.move((row, col))
if ret:
que_game2ui.put({
"game": self,
"info": "move"}, block=False)
pos2 = self.iterative_deepening(self.difficulty) # 这个函数很耗时
self.move(pos2)
que_game2ui.put({
"game": self,
"info": "move"}, block=False)
else:
que_game2ui.put({
"game": self,
"info": "Game Over"})
def queue_handler(self):
try:
task = que_ui2game.get(block=False)
if task["option"] == "move":
row, col = task["loc"]
self.moving(row, col)
self.gui.after(10, self.queue_handler)
except queue.Empty:
self.gui.after(10, self.queue_handler)
if __name__ == '__main__':
window = Tk()
gui = GUI(window)
t1 = threading.Thread(target=GAME, args=(window,))
t1.setDaemon = True
t1.start()
window.mainloop()
问题在于 GAME.moving 这里,分别有两次 put 操作,我设想的情况应该是:
但是根据实际症状,以及添加的调试信息来看,结果实际是这样的:
感觉没有达到拆分线程的目的,请问代码思路是哪里有问题呢?
1
NoAnyLove 2017-08-28 00:25:06 +08:00
原因很简单,你的`queue_handler`都是通过 Tkinter 组件的`after`方法调用的,这个方法调用`queue_handler`方法是在主线程( UI 线程中),也就是说`iterative_deepening`阻塞了 UI 线程,所以卡住了
|