Как отслеживать два 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% основной задачи, и поэтому я использую проценты, потому что иногда вы не знаете агрегированное число байтов, если вы имеют сложные множественные объектные процессы.