0

在此之前,我必須說我並不是很擅長Python編程,因爲我在其他語言中。我非常(太)惱火尋找其他解決方法,所以提前感謝您的幫助。我很喜歡在我的空閒時間製作Roguelike遊戲,所以我嘗試了很多方法來使用C++,C,C#,HTML5等爲我自己的遊戲做我自己的「引擎」實現和自己的引擎。從來沒有與LibTCOD合作過,因爲我從來沒有使用過C++工作。唉,這是我最喜歡的編程語言,這是一個我現在不會談論的問題,因爲它是用C++編寫的。Python線程凍結整個程序?

很不幸,LibTCOD看起來不錯,但提及和精確的文檔太少,所以我幾乎一個人工作。最後幾天我做了一個python包來輕鬆管理python和windows的LibTCOD功能,並使主遊戲代碼儘可能小。

我試圖添加的最終實現是將主遊戲循環傳遞給線程,處理每個基本遊戲功能(如鍵盤/鼠標更改和屏幕更新),並通過函數調用運行它。

一切工作正常......但不是在第一個循環步驟後,因爲它凍結了一切,並停止工作。

基本上,這是有問題的代碼:

def ioHandler(l): 
    lastx = 0 
    lasty = 0 
    lastk = None 
    c = 0 
    noEvent = 0 
    casted = False 
    while not tcod.console_is_window_closed(): 
     l.acquire() 
     try: 
      tcod.sys_check_for_event(tcod.EVENT_KEY_PRESS|tcod.EVENT_MOUSE,key,mouse) 
     finally: 
      l.release() 
     if mouse.lbutton_pressed: 
      casted = True 
      l.acquire() 
      try: 
       onClick(mouse, 'left') 
      finally: 
       l.release() 
     if mouse.rbutton_pressed: 
      casted = True 
      l.acquire() 
      try: 
       onClick(mouse, 'right') 
      finally: 
       l.release()   
     if mouse.cx != lastx or mouse.cy != lasty: 
      casted = True 
      l.acquire() 
      try: 
       lastx = mouse.cx 
       lasty = mouse.cy 
       onMouseMove(mouse) 
      finally: 
       l.release() 
     if key != lastk: 
      casted = True 
      l.acquire() 
      try: 
       lastk = key 
       onKeyPress(key) 
      finally: 
       l.release() 
     if not casted: noEvent += 1 
     l.acquire() 
     try: 
      onTickFrame(c+1) 
     finally: 
      l.release() 

大多數變量的使用有更清晰的瞭解調試的目的,(即使它凍結的「乾淨」的功能),所以我把那些有。

上面的 '高清' 從這裏稱爲:

def main_loop(): 
    l = threading.Lock() 
    tr = threading.Thread(target=ioHandler, args=(l,)) 
    #tr.daemon=True 
    tr.start() 

對於 '事件' 系統,我發現這個互聯網上:

class Event: 
    handlers = set() 
    def __init__(self): 
     self.handlers = set() 

    def handle(self, handler): 
     self.handlers.add(handler) 
     return self 

    def unhandle(self, handler): 
     try: 
      self.handlers.remove(handler) 
     except: 
      raise ValueError("Handler is not handling this event, so cannot unhandle it.") 
     return self 

    def fire(self, *args, **kargs): 
     for handler in self.handlers: 
      handler(*args, **kargs) 

    def getHandlerCount(self): 
     return len(self.handlers) 

    __iadd__ = handle 
    __isub__ = unhandle 
    __call__ = fire 
    __len__ = getHandlerCount 

作爲一個說明:我與Python 2.7一起工作,這是圖書館唯一的版本,真是太遺憾了。

我認爲事件系統可能是主要問題。再次讀取代碼,我認爲我也應該對這個while條件應用一個鎖,因此對整個循環來說,還是沒有必要?鎖是否以正確的方式應用?或者我應該使用其他方法使線程工作?

如果主遊戲循環在沒有線程的主腳本上執行,但一切都失敗時調用線程,或者即使它不是線程本身,但它被稱爲「外部」包中的其他函數,所以它不能成爲一個庫問題(我認爲)。

我不得不說,我只在Python中使用LibTCOD,因爲我無法使其工作(至少在Windows上)只有它。如果有幫助,我已經看到python庫的代碼只是原始C庫的「綁定」,所以理解python代碼並不是什麼大不了的事情。對於最後一條語句,我認爲這對python線程也是一個問題,或者我錯了嗎?如果有什麼我可以做的修復線程工具,請幫助我!

謝謝大家!我希望我的談話沒有讓你厭煩。

+0

上面的代碼有縮進問題。 –

+0

是的,它是這樣複製的,對不起。原始代碼確實沒有縮進錯誤。 –

+0

如果您可以編輯帖子並修復縮進,那麼我可以嘗試運行代碼以查看發生了什麼 –

回答

0

那裏,我不能把它及時地運行你的例子是缺少足夠的,所以我沒有給你一個已知的解決方案,但我有一些建議:

  1. 如果同一線程將發佈的是獲取它的鎖,我建議使用RLock() instead of Lock()

l = threading.RLock()

  • 爲了使代碼清潔器和更少的ERRO ř探針,我建議使用上下文管理器,所述鎖提供:
  • 代替:

    l.acquire(): 
    try: 
        tcod.sys_check_for_event(
         tcod.EVENT_KEY_PRESS | tcod.EVENT_MOUSE, key, mouse) 
    finally: 
        l.release() 
    

    嘗試:

    with l: 
        tcod.sys_check_for_event(
         tcod.EVENT_KEY_PRESS | tcod.EVENT_MOUSE, key, mouse) 
    
  • 至於還有什麼應該鎖定的問題。如果不理解所有的數據結構,這很難回答,但是一般來說任何將在多個線程中使用的東西都應該被鎖定。
  • +0

    感謝您的回覆。由於你的回答,我仍然認爲是'事件'系統,每個調用都需要越來越多的數據進行修改,並存儲在各種不同的角色中。但如果您仍然對幫助我感興趣,我會盡快將代碼上傳到某個地方,讓每個人都能更清楚地瞭解正在發生的事情。 –