У меня есть потребительский поток, который создает несколько рабочих потоков. Эти потоки должны переключаться между активным и ожидающим состояниями. Когда все рабочие потоки находятся в состоянии ожидания, это означает, что текущее задание выполнено. Как заставить потребительский поток ждать, пока все рабочие потоки перейдут в состояние ожидания? Я хочу, чтобы поведение было очень похоже на Thread.Join() во всех рабочих потоках, однако я хочу, чтобы потоки продолжали работать для следующего задания. Я не могу создавать новые потоки, потому что задания находятся в жестком цикле, а создание новых потоков требует больших затрат.
Как я могу заставить поток ждать, пока другой поток не будет ждать (С#)
Ответы (2)
Насколько я знаю, нет механизма, чтобы делать то, что вы хотите. (Thread.Join, но, поскольку вы не можете заблокировать, это не вариант)
Судя по предоставленной вами информации, похоже, что вы действительно строите конечный автомат, только для нескольких потоков.
Я бы создал Singleton и использовал бы его как конечный автомат. Потоки могут сигнализировать статусу Singleton.
Похоже, у вас есть неопределенное количество потоков, поэтому вам нужно будет поместить статус каждого в коллекцию. Я бы посмотрел здесь Thread Safe Collections чтобы найти правильный способ хранения информации о состоянии.
Надеюсь это поможет.
Извиняюсь за краткий ответ (может быть расширен позже), но вы, вероятно, WaitHandle.WaitAll в сочетании с ManualResetEvent. Вы должны передавать свои объекты ManualResetEvent
в каждый рабочий поток при их создании, сигнализировать им, когда они становятся бездействующими, и передавать весь набор дескрипторов в метод WaitHandle.WaitAll
, чтобы разбудить наблюдающий поток, когда они будут завершены. Вы также можете использовать функцию тайм-аута этого метода, если вы хотите периодически запускать какую-то задачу во время ожидания или выполнять какую-то операцию, если задача занимает слишком много времени.
Обратите внимание, что если ваши рабочие потоки предназначены для завершения после завершения операции (не совсем ясно, если это так), может быть более подходящим порождать их как задачи и использовать Task.WaitAll.
Редактировать: при быстром повторном прочтении кажется, что вы действительно хотите использовать задачи, а не пытаться повторно использовать полные рабочие потоки. Задачи используют потоки, которые были выделены из пула потоков, что устраняет накладные расходы на создание потока, о которых вы беспокоились, потому что потоки (обычно) будут готовы и ожидают работы. Вы можете просто создавать каждую задачу и ждать, пока они все будут выполнены.