我正在尝试使用适用于Python 2.7的新Minecraft Pi Edition API编写游戏。当我意识到代码的两个部分相互阻塞时,我几乎完成了游戏。如果我首先放置A部分,它将阻止B部分运行,直到A部分完成。如果我把B部分放在第一位,它会很慢地运行。我决定将两个部分分成两个独立的线程。 “
这是仍然存在问题的代码的缩减版本。我注意到如果我为两个类中的一个注释掉ClassName.start()
行,那么另一个类将运行而不会出错。
import mcpi.minecraft as minecraft
import threading
mc = minecraft.Minecraft.create()
class BlockCheckThread(threading.Thread):
def run(self):
while True:
event = mc.events.pollBlockHits()
class WinningCheckThread(threading.Thread):
def run(self):
while True:
blockTest = mc.getBlock(1, 1, 1,) == 50
def main():
WinningCheckThread().start() # If I comment out either of these .start() lines
BlockCheckThread().start() # the other class executes perfectly.
运行此错误如下:
Exception in thread Thread-2:
...
TypeError: Hit() takes exactly 5 arguments (1 given)
Exception in thread Thread-1:
...
ValueError: invalid literal for int() with base 10: '
要运行代码,您需要一个Raspberry Pi,并且需要从here下载Minecraft,然后您必须从api/python/
目录运行它。 (即它必须与它导入的mcpi
模块位于同一文件夹中。)
这是我第一次尝试线程化,所以不要在我的代码上大笑。我很想知道为什么这段代码不起作用,以及我应该怎么做才能解决它。
答案 0 :(得分:4)
您正在共享Minecraft
对象,并且它不是线程安全的。
Minecraft
对象只是一个客户端库,用于连接到使用命令minecraft-pi
启动的Minecraft服务器。您需要为每个线程创建一个Minecraft
对象,它应该没问题:
import mcpi.minecraft as minecraft
import threading
class BlockCheckThread(threading.Thread):
def run(self):
mc = minecraft.Minecraft.create()
while True:
event = mc.events.pollBlockHits()
class WinningCheckThread(threading.Thread):
def run(self):
mc = minecraft.Minecraft.create()
while True:
blockTest = mc.getBlock(1, 1, 1,) == 50
def main():
WinningCheckThread().start()
BlockCheckThread().start()
答案 1 :(得分:3)
Pi Edition的Python Minecraft客户端不是线程安全的。会发生什么是两个线程同时发送和接收数据。当响应混淆时(即BlockCheckThread
获得对WinningCheckThread
请求的响应,反之亦然),消息格式与线程期望获得的格式不匹配。
您可以简单地在Minecraft客户端的每次调用周围放置一个lock,以确保您一次只发送和接收一个项目。
我不知道Minecraft服务器是否支持它,但您也可以send multiple requests。为此,您需要一个能够跟踪未完成请求顺序的经理类。