- ВКонтакте
- РћРТвЂВВВВВВВВнокласснРСвЂВВВВВВВВРєРСвЂВВВВВВВВ
- РњРѕР№ Р В Р’В Р РЋРЎв„ўР В Р’В Р РЋРІР‚ВВВВВВВВРЎР‚
- Viber
- Skype
- Telegram
как правильно использовать Thread. многопоточность
В моем мини (проекте) по создании меню для игры. Пока меню активна то сокет ожидает подключение для сетевой игры. мне нужно три функции одновременно запустить но почему то когда запущены. и я выхожу из игры через красный крестик то зависает ошибка
Не знаю в чем проблема как решить
from pygame import display, draw, mouse, event, QUIT, Rect
from main import W, H
from threading import Thread
from time import sleep
import socket
screen = display.set_mode((W, H))
start_btn = Rect(W/2-200, H/2-80, 200, 80)
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind(('', 9531))
server.listen(2)
break_server = False
num_users = []
def acc():
while True:
conn, addr = server.accept()
num_users.append(conn)
def keep_users():
while True:
if num_users:
print('run')
for conn in num_users:
try: conn.send('/.,'.encode())
except: num_users.remove(conn)
print(conn)
sleep(0.5)
def menu():
global break_server
while not break_server:
display.update()
screen.fill((150, 150, 150))
draw.rect(screen, 'Blue', start_btn)
if mouse.get_pressed()[0] and start_btn.collidepoint(mouse.get_pos()):
print('ВСЕ')
break_server = True
for i in event.get():
if i.type == QUIT:
break_server = True
Thread(target=menu).start()
Thread(target=acc).start()
Thread(target=keep_users).start()
Ответы (1 шт):
Автор решения: gord1402
→ Ссылка
Процесс будет завершён только когда все потоки будут остановлены, у вас же после завершения main потоки продолжают действовать.
Начнём с keep_users, здесь достаточно добавить условие завершения цикла.
Теперь acc, поскольку server.accept()
- долгая функция вам прийдётся ждать до её завершения для проверки break_server, однако можно использовать поток-демон, такой поток завершится, когда все родительские потоки завершатся.
Вот изменённый код:
from pygame import display, draw, mouse, event, QUIT, Rect
from threading import Thread
from time import sleep
import socket
W, H = 640, 480
screen = display.set_mode((W, H))
start_btn = Rect(W / 2 - 200, H / 2 - 80, 200, 80)
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind(('', 9531))
server.listen(2)
break_server = False
num_users = []
def acc():
while not break_server:
conn, addr = server.accept()
num_users.append(conn)
def keep_users():
# Стоит смотреть когда основной поток остановлен, вместо вечного цикла
while not break_server:
if num_users:
print('run')
for conn in num_users:
try:
conn.send('/.,'.encode())
except:
num_users.remove(conn)
print(conn)
sleep(0.5)
def menu():
global break_server
while not break_server:
display.update()
screen.fill((150, 150, 150))
draw.rect(screen, 'Blue', start_btn)
if mouse.get_pressed()[0] and start_btn.collidepoint(mouse.get_pos()):
print('ВСЕ')
break_server = True
for i in event.get():
if i.type == QUIT:
break_server = True
# Поток-демон завершится когда все потоки не демоны завершатся
acc_thread = Thread(target=acc, daemon=True)
keep_users_thread = Thread(target=keep_users)
# Сначала запускаем потоки
acc_thread.start()
keep_users_thread.start()
# В главном потоке запускаем GUI
menu()
# После завершения GUI, ждём завершения keep_users_thread в главном потоке
keep_users_thread.join()
# Поток acc_thread завершится сам даже если будет в середине выполнения