2015-07-06 3 views
1

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

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

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

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

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

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

ответ

3

Да, вы можете запускать 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, также async, а также содержат дочерние NSProgresses. Вы более или менее хотите отменить текущий прогресс сразу после запуска асинхронной задачи и не дожидаться ее завершения.

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

+0

Выполняет ли дочерние задачи ваших задач «NSProgress» также «getCurrentWithPendingUnitCount:» и 'resignCurrent'? Моя проблема заключается в том, что у меня есть (эти совокупные задачи имеют свой собственный «NSProgress», а затем дальнейшие дочерние «NSProgress»), поэтому вызовы 'getCurrentWithPendingUnitCount:' и 'resignCurrent' вызовов вызывают или заказывают. Я полагаю, это не будет проблемой для вас, если ваши задачи просто используют leaf 'NSProgress' (два уровня« NSProgress »вместо трех). –

+0

Итак, мой пример для метода 'startAsyncTask1' создает локальный' NSProgress' и говорит, что у меня есть 10 пользователей для синхронизации, поэтому он устанавливает общее количество единиц в 10 и становится текущим с 10 ожидающими ответа. Он вызывает запускает вызовы api, которые асинхронны и уходят в отставку, прежде чем какой-либо из этих асинхронных вызовов вернется. Внутри этих вызовов API я создаю «NSProgess» для каждого вызова, НО ПРОИЗВОД НИЗКОГО УРОВНЯ НЕ ДОЛЖЕН ОТКАЗАТЬСЯ. поэтому в вызове API я никогда не отказываюсь от этого прогресса, я только обновляю завершенные единицы. –

+0

Я обновил ответ с большим количеством кода. Вы увидите, что конечная дочерняя задача не активируется и не сбрасывается. Мой реальный код мира - это задача, которая загружает все локальные объекты, загружает все локально созданные фотографии и загружает все новые объекты с сервера.Поэтому я создаю дочерний прогресс для каждого типа объекта, например 1 для задачи «Пользователи», 1 для задачи «Фото» вплоть до отдельных вызовов API. Шахта - 3 уровня глубины 'NSProgress'. –

Смежные вопросы