Если ваш вопрос касается того, как определить, какой поток загружает первый блок и когда этот первый блок готов к использованию, используйте событие для каждого потока и отслеживайте, какие блоки вы назначили каким потокам. Отслеживайте, какое событие вы передаете первому потоку (который будет загружать первый блок данных), событие, которое вы передаете второму потоку (для второго блока данных) и т. Д. Иметь основной поток или другой фоновый поток (чтобы не блокировать поток пользовательского интерфейса), дождитесь первого события. Когда первый поток заканчивает загрузку своего чанка, он устанавливает / сигнализирует о первом событии. Поток, который ожидает, затем проснется и может использовать первый кусок данных.
Другие потоки загрузки могут делать то же самое, сигнализируя о соответствующих событиях по завершении. Используйте событие ручного сброса, чтобы событие оставалось сигнальным, даже если никто не ждет его. Когда поток, которому нужны блоки данных по порядку, заканчивает обработку первого блока данных, он может ожидать 2-го события. Если о 2-м событии уже было сообщено, то ожидание немедленно вернется, и поток может начать обработку 2-го блока данных.
Для очень большой загрузки вы можете повторно использовать события и потоки в циклическом порядке. Порядок, в котором они завершаются, не важен, если поток, который использует блоки данных, использует их по порядку и ожидает соответствующих событий в порядке.
Если вы сообразительны и осторожны, вы, вероятно, можете сделать все это, используя только одно событие: создать глобальный массив указателей / объектов чанков данных, изначально равных нулю, рабочие потоки загружают чанки данных и назначают готовые чанки их соответствующий слот в глобальном массиве, а затем сигнализировать общее событие. Поток потребителя хранит счетчик порций данных, чтобы он знал, какой блок данных ему необходимо обработать следующим, ожидает общее событие и, когда он получает сигнал, смотрит на следующий слот в глобальном массиве, чтобы увидеть, появились ли там данные. Если в следующем слоте по-прежнему нет данных, потребительский поток возвращается к ожиданию события. Вам также понадобится способ, чтобы рабочие потоки знали, какой блок данных они должны загрузить следующим - глобального счетчика, защищенного мьютексом или получающего доступ с использованием interlockedadd / exchange, будет достаточно. Каждый рабочий поток увеличивает глобальный счетчик и загружает этот номер блока данных и присваивает результат n-му слоту в глобальном списке блоков данных.