我正在研究 Tkinter 桌面應用程式專案。當我需要使用運行后端代碼的執行緒時,我開始磕磕絆絆。我知道為了跨執行緒共享變數,我們應該使用全域變數。下面是最小的代碼。
obj = None
class Frame:
def __init__(self, frame):
self.middle_frame = frame
self.start_button = ttk.Button(self.middle_frame, text='Start', command=self.start)
self.start_button.grid(row=0, column=0)
self.stop_button = ttk.Button(self.middle_frame, text='Stop', command=self.stop)
self.stop_button.grid(row=0, column=1)
self.stop_button.config(state='disabled')
def start(self):
self.thread = threading.Thread(target=self.start_connection)
self.thread.start()
self.start_button.config(state='disabled')
self.stop_button.config(state='normal')
def start_connection(self):
global obj
obj = MainManager() # Starts the Backend Loop
def stop(self):
global obj
obj.close_connection() # Want to break the loop here
self.thread.join()
self.stop_button.config(state='disabled')
self.start_button.config(state='normal')
運行此代碼時,我得到 obj.close_connection() AttributeError:'NoneType' object has no attribute 'close_connection'. 但我期待 obj 成為 MainManager() 的物件。我哪里錯了?幫我解決這個問題。
uj5u.com熱心網友回復:
您的代碼問題tkinter與多執行緒無關或實際上與多執行緒無關。問題是MainManager在__init__方法內部啟動了回圈,如下所示:
class MainManager:
def __init__(self):
self.alive = True
# this part runs until stopped
self.start_doing_stuff()
def start_doing_stuff(self):
while self.alive:
sleep(1)
print('doing stuff')
def stop(self):
self.alive = False
這是一個與您的錯誤類似的代碼:
from threading import Thread
from time import sleep
obj = None
class MainManager:
def __init__(self):
self.alive = True
self.start_doing_stuff()
def start_doing_stuff(self):
while self.alive:
sleep(1)
print('doing stuff')
def stop(self):
self.alive = False
def test():
global obj
print('about to assign to my_global')
obj = MainManager()
print('assigned to my_global')
print(f'{obj=}')
t = Thread(target=test)
t.start()
sleep(3)
print(f'{obj=}')
obj.stop()
t.join()
因為該__init__方法直到stop方法被呼叫才會終止,所以MainManager()陳述句中的呼叫obj = MainManager()永遠不會終止,因此obj不會被賦值給。這意味著當obj.stop()被呼叫時,obj仍然是None。
這可以通過我使__init__方法終止并將長時間運行的代碼放入稍后呼叫的單獨方法中來解決:
from threading import Thread
from time import sleep
obj = None
class MainManager:
def __init__(self):
self.alive = True
def start_doing_stuff(self):
while self.alive:
sleep(1)
print('doing stuff')
def stop(self):
self.alive = False
def test():
global obj
print('about to assign to my_global')
obj = MainManager()
print('assigned to my_global')
obj.start_doing_stuff()
print(f'{obj=}')
t = Thread(target=test)
t.start()
sleep(3)
print(f'{obj=}')
obj.stop()
t.join()
uj5u.com熱心網友回復:
您是否匯入了 MainManager,是否運行了 start_connection()?
此外,您將分配委托給一個執行緒。您確定這obj與主執行緒的影響相同嗎?也許主執行緒保持“無”并且委托更改了副本中的值。添加日志或列印陳述句并確保obj為MainManager()物件分配并列印該物件的記憶體位置。在主類中也列印obj變數的記憶體位置。檢查它是否相同。
這是列印變數的記憶體地址的方式:
print(hex(id(your_variable)))
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/337153.html
