2

我正在嘗試使用Python 2.7的新Minecraft Pi Edition API編寫遊戲。當我意識到有兩段代碼互相阻塞時,我已經完成了遊戲。如果我先放置A節,則會阻止B節運行,直到A節完成。如果我先放置B部分,它會運行得非常慢。我決定我需要將兩部分分成兩個獨立的線程。 '當從線程類調用Python函數時行爲不如預期

這是仍然存在問題的代碼的減少版本。我注意到如果我爲兩個類中的一個註釋掉了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: ' 

要運行需要一個樹莓派的代碼,需要從here下載的Minecraft然後,您必須從運行api/python/目錄。 (即它必須與它正在導入的mcpi模塊在同一個文件夾中。)

這是我第一次嘗試線程化,所以不要在我的代碼中笑得太厲害。我很想知道爲什麼這段代碼不起作用,我該怎麼辦才能解決它。

回答

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() 
+0

謝謝。這工作!現在一切都很完美!好極了!太多驚歎號! – daviewales 2013-02-13 00:43:20

3

Pi版的Python Minecraft客戶端不是線程安全的。會發生什麼情況是兩個線程同時發送和接收數據。當響應混淆時(即BlockCheckThread得到對WinningCheckThread的請求的響應,反之亦然),消息格式與線程預期得到的不匹配。

您可以簡單地在每次調用Minecraft客戶端時放置一個lock,以確保您一次只發送和接收一個項目。

我不知道Minecraft服務器是否支持它,但您也可能能夠send multiple requests。爲此,您需要一個管理員類來跟蹤未完成請求的順序。

相關問題