Недавно начал изучать треды в питоне, и столкнулся с такой проблемой: мне нужно, чтобы функция "два" заканчивала выполнение после выполнения функции один в треде, но метод соединения не работает, видимо из-за цикла while true в третья функция. Я пытался использовать очередь, но это тоже не сработало.
Сам код:
from threading import Thread,Event
def one():
event.set()
thr.join()
for i in range(3):
print('some print')
time.sleep(1)
def two():
t = Thread(target=one)
t.start()
#with t.join() here the program does not work at all, same thing with event.set()
print('func two finished')
def three(callback, event):
c = 0
while True:
c += 1
time.sleep(1)
print('func 3 is working')
if c == 5:
two()
if event.is_set():
callback(c)
print('func 3 is stopped')
break
def callback(t):
print('callback ',t)
def thread(callback):
global event, thr
event = Event()
thr = Thread(target=three, args=(callback, event,))
thr.start()
thr.join()
thread(callback)
Текущий выход:
func 3 is working
func 3 is working
func 3 is working
func 3 is working
func 3 is working
func two finished
callback 5
func 3 is stopped
some print
some print
some print
Ожидал:
func 3 is working
func 3 is working
func 3 is working
func 3 is working
func 3 is working
callback 5
func 3 is stopped
some print
some print
some print
func two finished
Нужная вам последовательность получается небольшой перестановкой команд. Но непонятно, зачем нужны потоки, если все делается последовательно.
from threading import Thread, Event
import time
def one(event):
event.set()
for i in range(3):
print('some print')
time.sleep(1)
def two(event):
t = Thread(target=one, args=(event,))
t.start()
t.join()
print('func two finished')
def three(event):
c = 0
while True:
c += 1
time.sleep(1)
print('func 3 is working')
if c == 5:
callback(c)
print('func 3 is stopped')
two(event)
break
def callback(t):
print('callback ', t)
def thread():
event = Event()
thr = Thread(target=three, args=(event,))
thr.start()
thread()
--------------------------------
func 3 is working
func 3 is working
func 3 is working
func 3 is working
func 3 is working
callback 5
func 3 is stopped
some print
some print
some print
func two finished
Это комментарий, а не ответ.
Это не имеет никакого смысла:
t = Thread(target=one, args=(event,))
t.start()
t.join()
Нет смысла начинать новый поток, если вы не собираетесь делать что-то одновременно с этим потоком. Либо сделать это,
t = Thread(target=one, args=(event,))
t.start()
do_something_else_concurrently_with_thread_t(...)
t.join()
Или просто вызовите функцию вместо создания нового потока для ее вызова:
one(event)
Если вы не хотите параллелизма, вам не нужны потоки.
Ваша программа создает взаимоблокировку, если вы раскомментируете этот t.join() вызов функции two;
Поток thr не может завершиться до тех пор, пока не завершится поток t, потому что поток thr вызывает t.join() в функции two.
Поток t не может завершиться до тех пор, пока не завершится поток thr, потому что поток t вызывает thr.join() в функции one.
Ни один поток не может завершиться до тех пор, пока не завершится другой поток. Следовательно, ни один поток никогда не может завершиться.
Почему one присоединился к теме thr?
def one():
event.set()
thr.join() # What were you trying to do here?
for i in range(3):
print('some print')
time.sleep(1)
Ваша программа выдаст желаемый результат, если вы закомментируете этот вызов соединения и раскомментируете вызов t.join() в функции two.
После запуска кода я понимаю, что «не работает» вы имеете в виду, что программа завершена до того, как все отпечатки будут напечатаны. Причина в том, что вы присоединяетесь к thr треду дважды, один из них к основному треду. Последовательность возврата соединения не гарантируется. Когда основной поток завершается, все потоки, созданные программой, также завершаются, поэтому они завершаются несмотря ни на что.
То же самое при установке события, оно заставляет основной поток выйти и убить оставшиеся потоки.
Чтобы сделать то, что вы намереваетесь, вы должны дождаться одного потока в основном потоке.
from threading import Thread,Event
def one():
event.set()
thr.join()
for i in range(3):
print('some print')
time.sleep(1)
def two():
t = Thread(target=one)
t.start()
#with t.join() here the program does not work at all, same thing with event.set()
print('func two finished')
def three(callback, event):
c = 0
while True:
c += 1
time.sleep(1)
print('func 3 is working')
if c == 5:
two()
if event.is_set():
callback(c)
print('func 3 is stopped')
break
def callback(t):
print('callback ',t)
def thread(callback):
global event, thr
event = Event()
thr = Thread(target=three, args=(callback, event,))
thr.start()
thr.join()
thread(callback)
Обратите внимание, что, как уже было сказано, это может быть полезно для изучения целей, но его необходимо изменить, если вы действительно хотите использовать его в реальном коде.