小能豆

pyagme 屏幕无法与多线程一起使用

py

我正在使用 python 2.7.14,目前正在尝试使用多处理模块同时在 pygame 屏幕的两侧进行绘制(2 个线程从单个 pygame 屏幕调用函数),但每次我从屏幕调用函数时(例如screen.get_width())都会引发以下错误:

Process Process-1:
Traceback (most recent call last):
  File "C:\Python27\lib\multiprocessing\process.py", line 267, in _bootstrap
    self.run()
  File "C:\Python27\lib\multiprocessing\process.py", line 114, in run
    self._target(*self._args, **self._kwargs)
  File "C:\Python27\multiplayer.py", line 9, in single_core_game
    print screen.get_width()
error: display Surface quit

我知道通过线程写入并不是最优雅的方式,因此我很高兴听到其他选择。


阅读 18

收藏
2024-12-10

共1个答案

小能豆

在 Python 中使用 multiprocessing 时遇到这种错误,通常是因为 Pygame 的 Surface(例如屏幕对象)无法在多个进程间共享。Pygame 初始化的显示窗口和相关对象属于主进程,不能在子进程中直接使用。

解决这个问题的一种方法是:让所有的图形更新和渲染操作都在主进程中进行,而子进程只负责计算或其他任务,然后通过队列或管道等机制与主进程通信。这样你就可以保持绘图操作的单线程,而同时进行多进程的计算任务。

示例代码

你可以像下面这样调整你的代码:

import pygame
import multiprocessing
import time

# 初始化Pygame
pygame.init()

# 创建屏幕
screen = pygame.display.set_mode((800, 600))

def draw_on_side(queue, side):
    """这个函数将绘制内容发送给主进程"""
    while True:
        if side == 'left':
            color = (255, 0, 0)  # 红色
        else:
            color = (0, 255, 0)  # 绿色

        queue.put(color)  # 将颜色信息发送到主进程
        time.sleep(1)

def main():
    queue = multiprocessing.Queue()

    # 启动两个子进程
    process_left = multiprocessing.Process(target=draw_on_side, args=(queue, 'left'))
    process_right = multiprocessing.Process(target=draw_on_side, args=(queue, 'right'))

    process_left.start()
    process_right.start()

    # 游戏循环
    running = True
    while running:
        screen.fill((0, 0, 0))  # 清空屏幕

        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                running = False

        # 从队列获取绘制信息并更新屏幕
        if not queue.empty():
            color = queue.get()
            if color == (255, 0, 0):  # 红色代表左侧
                pygame.draw.rect(screen, color, pygame.Rect(0, 0, 400, 600))  # 左侧画红色
            elif color == (0, 255, 0):  # 绿色代表右侧
                pygame.draw.rect(screen, color, pygame.Rect(400, 0, 400, 600))  # 右侧画绿色

        pygame.display.flip()  # 更新屏幕

    process_left.terminate()
    process_right.terminate()

    pygame.quit()

if __name__ == "__main__":
    main()

解释:

  1. 主进程负责 Pygame 的显示和绘图:所有的图形渲染都通过 screen 进行,确保 Pygame 只在主进程中调用。
  2. 子进程负责计算或其他任务:例如 draw_on_side 函数负责计算绘制的颜色或图形信息,并通过队列将结果传递给主进程。
  3. 使用 multiprocessing.Queue 进行进程间通信:通过队列将数据传递到主进程,而主进程读取这些数据并进行绘制。

这种方法避免了多进程共享 Pygame 对象的问题,同时也保留了多进程的计算优势。

2024-12-10