Как отслеживать два NSProgress параллельно?

У меня есть две большие задачи с несколькими подзадачами каждая. У каждой подзадачи есть ребенок NSProgress который я обновляю вручную. Каждое большое задание содержит родителей NSProgress с несколькими

[progress becomeCurrentWithPendingUnitCount:1.0]
// Perform subtask which generates the child `NSProgress`.
[progress resignCurrent]

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

Моя проблема в том, что я хочу выполнять эти две большие задачи параллельно, и я хочу отслеживать их прогресс в целом. Есть какой-либо способ сделать это?

Я пытался создать NSProgress объект на внешнем уровне, чтобы обернуть две большие задачи NSProgress (так три NSProgress уровней в общей сложности), но проблема в том, что две задачи "сражаются" при обновлении прогресса. То есть одна задача может быть выполнена becomeCurrentWithPendingUnitCount: и тогда другая задача может быть выполнена resignCurrent что вызывает исключение (так как вторая задача NSProgress не актуально).

Решение двух задач последовательно, а не параллельно решает проблему, но я действительно хотел бы выполнить их одновременно. Есть идеи?

1 ответ

Да, вы можете запустить 2 асинхронные операции параллельно с NSProgress, Вот фрагмент того, что я делаю.

   dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
        [self.progress becomeCurrentWithPendingUnitCount:40];
        [self startAsyncTask1];
        [self.progress resignCurrent];
        [self.progress becomeCurrentWithPendingUnitCount:60];
        [self startAsyncTask2];
        [self.progress resignCurrent];
    });

- (void)startAsyncTask1{
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
        NSProgress *taskProgress = [NSProgress progressWithTotalUnitCount:allUsers.count];
        [taskProgress becomeCurrentWithPendingUnitCount:allUsers.count];
        [self startUploadingAllUsers];
        [taskProgress resignCurrent];
    });
}
-(void)startUploadingAllUsers{
    for(id user in allUsers){
        [self uploadUser:user];
    }
}
-(void)uploadUser:(id)user{
    NSProgress *taskProgress = [NSProgress progressWithTotalUnitCount:user.photos.count];
    //Do upload and in completion of photo upload increment taskProgress.completedUnitCount
    //This last task does not get resigned. It does not become active either.
}

Вы должны убедиться, что ваши 2 задачи являются асинхронными. Это означает, что вызов в отставку вызывается сразу, даже если задача все еще выполняется. Когда я попытался уйти в отставку при завершении асинхронной задачи, я получил эту ошибку из-за того, что NSProgress уже подал в отставку в другом месте. Как и в моем примере, Task1 и Task2 также асинхронны и содержат дочерние NSProgress. Вы более или менее хотите отложить текущий прогресс сразу после запуска асинхронной задачи и не дожидаясь ее завершения.

В качестве примечания я предпочитаю использовать 100 единиц в качестве ожидающих, чтобы я мог думать о каждой задаче в процентах от нее. Вы также можете использовать количество байтов для ожидающих устройств, но я склонен делать это в нижестоящих дочерних процессах, где происходит фактическая обработка данных, а не в родительском процессе. Как и в моем примере, я отправляю асинхронную задачу для загрузки всех новых объектов User в API и процесс загрузки всех новых фотографий пользователя. Задача photo подсчитывает размер фотографии в байтах и ​​использует ее для обновления дочернего процесса, но родительская задача составляет около 40% основной задачи, и поэтому я использую проценты, потому что иногда вы не знаете агрегированное число байтов, если вы имеют сложные множественные объектные процессы.

Другие вопросы по тегам