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

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

29.01.2017, 00:05. Показов 3151. Ответов 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
8488 / 6155 / 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
8488 / 6155 / 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
8488 / 6155 / 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
8488 / 6155 / 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
8488 / 6155 / 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
8488 / 6155 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
29.01.2017, 20:13  [ТС]
Выглядит так:
Кликните здесь для просмотра всего текста
0
Эксперт С++
 Аватар для Avazart
8488 / 6155 / 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
8488 / 6155 / 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
Ответ Создать тему
Новые блоги и статьи
1С: Контроль уникальности заводского номера
Maks 23.03.2026
Алгоритм контроля уникальности заводского (или серийного) номера на примере документа выдачи шин для спецтехники с табличной частью. Данные берутся из регистра сведений, по которому настроено. . .
Хочу заставить корпорации вкладываться в здоровье сотрудников: делаю мат модель здравосохранения
anaschu 22.03.2026
e7EYtONaj8Y Z4Tv2zpXVVo https:/ / github. com/ shumilovas/ med2. git
1С: Программный отбор элементов справочника по группе
Maks 22.03.2026
Установка программного отбора элементов справочника "Номенклатура" из модуля формы документа. В качестве фильтра для отбора справочника служит группа номенклатуры. Отбор по наименованию группы. . .
Как я обхитрил таблицу Word
Alexander-7 21.03.2026
Когда мигает курсор у внешнего края таблицы, и нам надо перейти на новую строку, а при нажатии Enter создается новый ряд таблицы с ячейками, то мы вместо нервных нажатий Энтеров мы пишем любые буквы. . .
Krabik - рыболовный бот для WoW 3.3.5a
AmbA 21.03.2026
без регистрации и смс. Это не торговля, приложение не содержит рекламы. Выполняет свою непосредственную задачу - автоматизацию рыбалки в WoW - и ничего более. Однако если админы будут против -. . .
1С: Программный отбор элементов справочника по значению перечисления
Maks 21.03.2026
Установка программного отбора элементов справочника "Сотрудники" из модуля формы документа. В качестве фильтра для отбора служит значение перечислений. / / Событие "НачалоВыбора" реквизита на форме. . .
Переходник USB-CAN-GPIO
Eddy_Em 20.03.2026
Достаточно давно на работе возникла необходимость в переходнике CAN-USB с гальваноразвязкой, оный и был разработан. Однако, все меня терзала совесть, что аж 48-ногий МК используется так тупо: просто. . .
Оттенки серого
Argus19 18.03.2026
Оттенки серого Нашёл в интернете 3 прекрасных модуля: Модуль класса открытия диалога открытия/ сохранения файла на Win32 API; Модуль класса быстрого перекодирования цветного изображения в оттенки. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru