2 回答

TA貢獻(xiàn)1921條經(jīng)驗(yàn) 獲得超9個(gè)贊
Python 線程可能不是您嘗試做的工作的理想工具。
盡管將 Python 線程視為并發(fā)運(yùn)行可能很誘人,但事實(shí)并非如此:全局解釋器鎖 (GIL) 只允許一個(gè)線程控制 Python 解釋器。更多信息
正因?yàn)槿绱耍?code>arcade.Window對象無法及早控制 Python 解釋器并運(yùn)行其所有更新函數(shù),因?yàn)?GIL 始終“專注”simulation
于physics_thread
.
GIL 只會(huì)在physics_thread
運(yùn)行一定數(shù)量的指令或使用which 在線程上執(zhí)行physics_thread
設(shè)置為睡眠后才釋放對 的關(guān)注并在其他線程上尋找其他事情要做。這正是您憑經(jīng)驗(yàn)發(fā)現(xiàn)的恢復(fù)程序預(yù)期行為的方法。time.sleep()
這是一個(gè)稱為線程饑餓的典型問題的示例,可以通過使用多處理庫來解決。這會(huì)帶來更多的復(fù)雜性,但會(huì)將您的 CPU 密集型計(jì)算和基于事件的輕量級(jí)接口分開在不同的進(jìn)程中,從而解決您的問題。

TA貢獻(xiàn)1789條經(jīng)驗(yàn) 獲得超8個(gè)贊
我研究了使用多處理而不是線程。
該multiprocessing.Pipe對象確保了雙工通信并使整個(gè)事情變得更加順暢。我現(xiàn)在還可以確保模擬的實(shí)時(shí)運(yùn)行。
兩邊的每個(gè)更新循環(huán),只需使用send()andrecv()命令。尚未測試邊緣情況,但似乎工作順利。
我將修改添加到上面發(fā)布的示例中:
import time
import arcade
from multiprocessing import Process, Pipe
from math import sin, pi
class DisplayWindow(arcade.Window):
def __init__(self, connection: Pipe):
super().__init__(500, 500)
self.connection: Pipe = connection # multiprocessing.Pipe
self.position: float = 0 # GUI Display state
self.user_input: float = 1.0 # Input to simulation
self.FPS: float = 0 # Frames per second estimation
def on_update(self, delta_time: float):
self.FPS = 1. / delta_time
# Communicate with simulation:
self.connection.send(self.user_input)
self.position = self.connection.recv()
def on_draw(self):
arcade.start_render()
arcade.draw_text(f'FPS: {self.FPS:0.0f}', 20, 20, arcade.color.WHITE)
arcade.draw_point(self.position, self.height/2, arcade.color.WHITE, 10)
def on_key_release(self, symbol: int, modifiers: int):
if symbol == arcade.key.W:
self.user_input = 1.8
elif symbol == arcade.key.S:
self.user_input = 0.3
# Separate Process target to simulate physics:
def simulation(connection: Pipe):
t_0 = time.time()
while True:
freq = connection.recv() * 2 * pi # Receive GUI user input
t = time.time() - t_0
x = sin(freq * t) * 250 + 250
connection.send(x) # Send state to GUI
def main():
parent_con, child_con = Pipe()
display_window = DisplayWindow(connection=parent_con)
physics = Process(target=simulation, args=(child_con,), daemon=True)
physics.start()
arcade.run()
physics.terminate()
return 0
if __name__ == '__main__':
main()
添加回答
舉報(bào)