С Новым годом! Форум программистов, компьютерный форум, киберфорум
Python
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.53/15: Рейтинг темы: голосов - 15, средняя оценка - 4.53
Эксперт С++
 Аватар для Avazart
8484 / 6151 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30

Можно ли ждать завершения одновременно сразу нескольких потоков?

29.01.2017, 00:05. Показов 3127. Ответов 16
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Можно ли ждать завершения одновременно сразу нескольких потоков или выставления нескольких эвентов ?
Нечто вроде аналога WaitForMultiplyObjects().

В псевдокоде нечто вроде:
Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import threading
import time
 
def thread_function(i):
    time.sleep(i)
 
def main():
    threads = []
    for i in range(2):
        thread = threading.Thread(target=thread_function, args=(i))
        threads.append(thread)
 
    index_of_thread = wait_one_of_threads(threads) #  и wait_all_threads(threads)
 
    print(index_of_thread, "finished first...")
 
if __name__ == '__main__':
    main()
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
29.01.2017, 00:05
Ответы с готовыми решениями:

Правильно создать пул потоков, запустить эти потоки одновременно и дождаться их завершения
Добрый день! Подскажите пожалуйста, как правильно создать пул потоков, запустить эти потоки одновременно и дождаться завершения всех...

Как дождаться завершения нескольких потоков
Добрый день. Столкнулся с такой проблемой: в методе main() создается n одинаковых потоков, каждый из которых обрабатывает по файлу......

Запуск нескольких независимых потоков. Дождаться завершения всех (C++ 11)
Доброго времени суток. Подскажите, как запустить несколько независимых потоков, но дождаться, пока все завершатся? В каждом потоке есть...

16
2742 / 2341 / 620
Регистрация: 19.03.2012
Сообщений: 8,830
29.01.2017, 00:08
Python
1
2
for i in threads:
    i.join()
0
Эксперт С++
 Аватар для Avazart
8484 / 6151 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
29.01.2017, 00:12  [ТС]
Цитата Сообщение от alex925 Посмотреть сообщение
Python
1
2
for i in threads:
    i.join()
Это совсем не то.

Мне нужно знать завершился ли один из потоков и какой именно...
(И естественно без бесконечных циклов пожирающих ресурсы)

Тоже самый вопрос возникает насчет объектов-событий и процессов.
0
2742 / 2341 / 620
Регистрация: 19.03.2012
Сообщений: 8,830
29.01.2017, 00:27
Avazart, нужно на голом Python? Если использовать pyqt, то достаточно просто сделать.

Или можно использовать очереди. Каждый поток перед завершением пусть что нибудь кидает в очередь, а в главном потоке вызоваем метод get, который будет ждать, пока в очереди появиться хоть что-то.
0
Эксперт С++
 Аватар для Avazart
8484 / 6151 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
29.01.2017, 00:29  [ТС]
Я нашел решение для потоков, через очередь.

Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
import threading
import queue
import random
import time
 
 
def thread_function(i, q):
    time.sleep(random.randint(1, 5))
    q.put(i)
 
 
def main():
    q = queue.Queue()
    threads = []
    for i in range(2):
        thread = threading.Thread(target=thread_function, args=(i, q))
        threads.append(thread)
        thread.start()
 
    counter = 2
    while counter:
        i = q.get()
        print("#{} finished.".format(i))
        counter -= 1
 
    print("Done!")
 
 
if __name__ == '__main__':
    main()
Теперь вопросы:
  1. Можно ли сделать лучше/проще?
  2. Можно ли сделать подобное для процессов и событий?
0
2742 / 2341 / 620
Регистрация: 19.03.2012
Сообщений: 8,830
29.01.2017, 00:29
2. Для процессов можно сделать
0
Эксперт С++
 Аватар для Avazart
8484 / 6151 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
29.01.2017, 16:30  [ТС]
Задумка вот в чем:
Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
import multiprocessing
import threading
import random
import time
 
def process_function(i, q):
    time.sleep(random.randint(1, 5))
    q.put(i)
 
 
def thread_function(n):
    q = multiprocessing.Queue()
    for i in range(n):
        process = multiprocessing.Process(target=process_function, args=(i, q))
        process.start()
 
    counter = n
    while counter:
        i = q.get()
        print("#{} finished.".format(i))
        counter -= 1
        # Послать сигнал с результатом в основной поток Qt эвент лупу !!!
 
def main():
    thread = threading.Thread(target=thread_function,args=(5,))
    thread.start()
    thread.join()
    print("Done!")
 
if __name__ == '__main__':
    main()

Т.е что бы решить проблему Реализация и использование потоков в PyQt

Добавлено через 15 часов 50 минут
Все бы хорошо, но если заменить на ProcessPoolExecutor процессы виснут намертво.

Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
from concurrent.futures import ProcessPoolExecutor
import multiprocessing
import threading
import random
import time
from datetime import datetime
 
 
def process_function(i, q):
    time.sleep(random.randint(5, 20))
    q.put(i)
 
 
def thread_function(n):
    manager = multiprocessing.Manager()
    q = manager.Queue()
    # for i in range(n):
    #     process = multiprocessing.Process(target=process_function, args=(i, q))
    #     process.start()
 
    with ProcessPoolExecutor(max_workers=2) as executor:
        for i in range(n):
            executor.submit(process_function, i)
 
    counter = n
    while counter:
        i = q.get()
        print("{1} #{0} finished.".format(i, datetime.now().strftime('%H:%M:%S')))
        counter -= 1
    print("Done!")
 
 
def main():
    thread = threading.Thread(target=thread_function, args=(5,))
    thread.start()
    thread.join()
 
 
if __name__ == '__main__':
    main()
0
29.01.2017, 17:28
 Комментарий модератора 
Avazart, называйте темы по-нормальному, а не набором ключевых слов.
0
757 / 306 / 190
Регистрация: 20.05.2016
Сообщений: 593
29.01.2017, 18:15
Вы, кажется, q забыли передать
Python
1
executor.submit(process_function, i, q)
Так процессы завершаются, но почему-то, на randint не взирая, совершенно синхронно

Как приблизительный вариант (если уж PoolExecutor)

Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
from concurrent.futures import ProcessPoolExecutor
import multiprocessing
import threading
import random
import time
from datetime import datetime
 
 
def process_function(i):
    start = datetime.now().strftime('%H:%M:%S')
    t = random.randint(5, 20)
    time.sleep(t)
    return i, start, t
 
 
def thread_function(n):
  
    def fn(fs):
        i, start, delay = fs.result()
        print("{1} #{0} finished. Result {2}: start - {3}, delay - {4}".format(fs, datetime.now().strftime('%H:%M:%S'), i, start, delay))
 
    with ProcessPoolExecutor(max_workers=2) as executor:
        for i in range(n):
            e = executor.submit(process_function, i)
            
            e.add_done_callback(fn)
    
 
def main():
    thread = threading.Thread(target=thread_function, args=(5,))
    thread.start()
    thread.join()
 
 
if __name__ == '__main__':
    main()
0
Эксперт С++
 Аватар для Avazart
8484 / 6151 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
29.01.2017, 19:51  [ТС]
Цитата Сообщение от shsv Посмотреть сообщение
Вы, кажется, q забыли передать
Не меняет ситуации, опечатка.

Цитата Сообщение от shsv Посмотреть сообщение
Так процессы завершаются, но почему-то, на randint не взирая, совершенно синхронно
Там в пуле два процесса, учли?

Через колбек я тоже уже догадался, но обнаружил интересную вещь:
Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
import os
from concurrent.futures import ProcessPoolExecutor
import multiprocessing
import threading
import random
import time
from datetime import datetime
 
 
def process_function(i):
    delay = random.randint(5, 20)
    print("thread th id: {0}, pid: {1} value: {2} time: {3} delay: {4}"
          .format(threading.get_ident(), os.getppid(),
                  i,
                  datetime.now().strftime('%H:%M:%S'),
                  delay))
    time.sleep(delay)
    return i ** 2
 
def done_callback(future):
    print("callback th id: {0}, pid: {1} result: {2} time: {3}"
          .format(threading.get_ident(), os.getppid(),
                   future.result(), datetime.now().strftime('%H:%M:%S')))
 
 
def thread_function(n):
    print("creator th id: {0}, pid: {1}".format(threading.get_ident(), os.getppid()))
    with ProcessPoolExecutor(max_workers=2) as executor:
        for i in range(n):
            future = executor.submit(process_function, i)
            future.add_done_callback(done_callback)
 
 
def main():
    print("main th id: {0}, pid: {1}".format(threading.get_ident(),os.getppid()))
    thread = threading.Thread(target=thread_function, args=(5,))
    thread.start()
    thread.join()
 
 
if __name__ == '__main__':
    main()
Колбеки иногда вызывается совсем с левого потока, т.е это и не основной поток и не создающий процессы.
А иногда колбеки все же вызываются из создающего потока.

Добавлено через 4 минуты
У меня выводит примерно следующее:
main th id: 2648, pid: 4536
creator th id: 4048, pid: 4536
thread th id: 2108, pid: 5328 value: 0 time: 17:35:56 delay: 12
thread th id: 3020, pid: 5328 value: 1 time: 17:35:56 delay: 16
callback th id: 2552, pid: 4536 result: 0 time: 17:36:08
thread th id: 2108, pid: 5328 value: 2 time: 17:36:08 delay: 6
callback th id: 2552, pid: 4536 result: 1 time: 17:36:12
thread th id: 3020, pid: 5328 value: 3 time: 17:36:12 delay: 9
callback th id: 2552, pid: 4536 result: 4 time: 17:36:14
thread th id: 2108, pid: 5328 value: 4 time: 17:36:14 delay: 17
callback th id: 2552, pid: 4536 result: 9 time: 17:36:21
callback th id: 2552, pid: 4536 result: 16 time: 17:36:31
Добавлено через 36 минут
Вообще какая то непонятная ерунда, я изменил max_workers=5 т.е по сути на каждую задачу должно быть по одному процессу, но выдает что все задачи находятся в одном процессе:

main th_id: 4060, pid: 4536
creator th_id: 984, pid: 4536

thread th_id: 6104, pid: 1400 value: 0 time: 18:06:14 delay: 11
thread th_id: 1952, pid: 1400 value: 1 time: 18:06:14 delay: 8
thread th_id: 1372, pid: 1400 value: 2 time: 18:06:14 delay: 13
thread th_id: 5508, pid: 1400 value: 3 time: 18:06:14 delay: 11
thread th_id: 196, pid: 1400 value: 4 time: 18:06:14 delay: 17

callback th_id: 2080, pid: 4536 result: 1 time: 18:06:22
callback th_id: 2080, pid: 4536 result: 0 time: 18:06:25
callback th_id: 2080, pid: 4536 result: 3 time: 18:06:25
callback th_id: 2080, pid: 4536 result: 2 time: 18:06:27
callback th_id: 2080, pid: 4536 result: 4 time: 18:06:31
Это os.getppid() врёт?

Добавлено через 41 минуту
Судя по диспетчеру задач действительно создается 5 процессов, но заметно что в одном из этих процессов а именно у того чей pid выводит создается ~5...7 потоков, в остальных процессах ~2...4 потока.

Т.е. как работает и можно ли назвать это нормальной работой ProcessPoolExecutor вообще ничего нельзя сказать.
0
757 / 306 / 190
Регистрация: 20.05.2016
Сообщений: 593
29.01.2017, 19:53
os.getppid() - родительский процесс, так что, вроде, верно всё. А с потоком да, не понятно. Там в реализации создается поток, который
Manages the communication between this process and the worker processes.
должно быть из него колбэки и вызываются, но я не разобрался пока

У меня в процессах по одному потоку, кроме родительского, там их 4 ~ 5
1
Эксперт С++
 Аватар для Avazart
8484 / 6151 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
29.01.2017, 20:09  [ТС]
Цитата Сообщение от shsv Посмотреть сообщение
os.getppid() - родительский процесс, так что, вроде, верно всё.
Да заменил на

Python
1
2
from win32process import GetCurrentProcessId
GetCurrentProcessId()
Все верное показывает теперь.
0
Эксперт С++
 Аватар для Avazart
8484 / 6151 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
29.01.2017, 20:13  [ТС]
Выглядит так:
Кликните здесь для просмотра всего текста
0
Эксперт С++
 Аватар для Avazart
8484 / 6151 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
29.01.2017, 20:20  [ТС]
Цитата Сообщение от shsv Посмотреть сообщение
должно быть из него колбэки и вызываются, но я не разобрался пока
В приципе, в моем случае думаю это не важно, я собираюсь вызывать из него слот виджета Qt потокобезопасным способом.
0
757 / 306 / 190
Регистрация: 20.05.2016
Сообщений: 593
29.01.2017, 20:41
Цитата Сообщение от shsv Посмотреть сообщение
должно быть из него колбэки и вызываются, но я не разобрался пока
Нельзя сказать, что всё кристально ясно, но да, точно, колбеки вызываются из него

Добавлено через 3 минуты
(Текущий процесс - os.getpid(), разница в одной p)
1
Эксперт С++
 Аватар для Avazart
8484 / 6151 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
29.01.2017, 21:27  [ТС]
Оказывается есть такая штука которую я искал concurrent.futures.wait c флагами:

Python
1
 concurrent.futures.wait(fs, timeout=None, return_when=ALL_COMPLETED)
FIRST_COMPLETED The function will return when any future finishes or is cancelled.
FIRST_EXCEPTION The function will return when any future finishes by raising an exception. If no future raises an exception then it is equivalent to ALL_COMPLETED.
ALL_COMPLETED The function will return when all futures finish or are cancelled.

Можно было её использовать...

Добавлено через 6 минут

Не по теме:

Касательно использование этого для использования совместно с Qt интерфейсом Реализация и использование потоков в PyQt

1
757 / 306 / 190
Регистрация: 20.05.2016
Сообщений: 593
29.01.2017, 22:21
Чтобы как-то подытожить с потоками
В моём случае в главном (родительском, том что обозначен как main) процессе 4 потока:
1. Главный поток - main,
2. Поток, явно нами созданный - creator,
3. Поток, созданный реализацией ProcessPoolExecutor, для обеспечения взаимодействия между главным и, создаваемыми PoolExecutor'ом, рабочими процессами (из него, в частности, вызываются колбеки),
4. Наконец, последний, создан реализацией multiprocessing.Queue. Queue используется внутри ProcessPoolExecutor'а для складирования результатов работы дочерних процессов.

В дочерних процессах по одному потоку.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
29.01.2017, 22:21
Помогаю со студенческими работами здесь

Запуск одновременно нескольких потоков
Вот как запустить например сразу 20 потоков ? что бы работа, например http запроса или еще что-то выполнялась быстрее. Запуск одного...

Запуск нескольких потоков одновременно
Здравствуйте. Подскажите пожалуйста как запустить несколько потоков в такой ситуации. Есть некий путь к папке, необходимо по этому пути...

Запуск нескольких потоков одновременно
Здравствуйте. У меня есть стэк объектов, с которыми нужно произвести какие-то действия. Причем работать нужно в трех потоках. То...

Корректная работа нескольких потоков одновременно
Дорогие пользователи возникла проблема... Мне нужно запустить програму-чекер в многопотоке... Но как там много идёт время выполнения...

Как подождать завершения нескольких потоков, и если после минуты не завершились продолжать выполнение?
Как подождать завершения нескольких потоков, и если после минуты не завершились продолжать выполнение программы дальше?


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
17
Ответ Создать тему
Новые блоги и статьи
Изучаю kubernetes
lagorue 13.01.2026
А пригодятся-ли мне знания kubernetes в России?
Сукцессия микоризы: основная теория в виде двух уравнений.
anaschu 11.01.2026
https:/ / rutube. ru/ video/ 7a537f578d808e67a3c6fd818a44a5c4/
WordPad для Windows 11
Jel 10.01.2026
WordPad для Windows 11 — это приложение, которое восстанавливает классический текстовый редактор WordPad в операционной системе Windows 11. После того как Microsoft исключила WordPad из. . .
Classic Notepad for Windows 11
Jel 10.01.2026
Old Classic Notepad for Windows 11 Приложение для Windows 11, позволяющее пользователям вернуть классическую версию текстового редактора «Блокнот» из Windows 10. Программа предоставляет более. . .
Почему дизайн решает?
Neotwalker 09.01.2026
В современном мире, где конкуренция за внимание потребителя достигла пика, дизайн становится мощным инструментом для успеха бренда. Это не просто красивый внешний вид продукта или сайта — это. . .
Модель микоризы: классовый агентный подход 3
anaschu 06.01.2026
aa0a7f55b50dd51c5ec569d2d10c54f6/ O1rJuneU_ls https:/ / vkvideo. ru/ video-115721503_456239114
Owen Logic: О недопустимости использования связки «аналоговый ПИД» + RegKZR
ФедосеевПавел 06.01.2026
Owen Logic: О недопустимости использования связки «аналоговый ПИД» + RegKZR ВВЕДЕНИЕ Введу сокращения: аналоговый ПИД — ПИД регулятор с управляющим выходом в виде числа в диапазоне от 0% до. . .
Модель микоризы: классовый агентный подход 2
anaschu 06.01.2026
репозиторий https:/ / github. com/ shumilovas/ fungi ветка по-частям. коммит Create переделка под биомассу. txt вход sc, но sm считается внутри мицелия. кстати, обьем тоже должен там считаться. . . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru