简体   繁体   English

如何并行跟踪两个NSProgress?

[英]How to track two NSProgress in parallel?

I have two different big tasks with several subtasks each. 我有两个不同的大任务,每个任务都有几个子任务。 Each subtask has a child NSProgress which I update manually. 每个子任务都有一个子NSProgress ,我手动NSProgress进行更新。 Each big task hosts a parent NSProgress with several 每个大任务都托管一个父NSProgress其中有几个

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

calls at different times. 在不同时间打电话。 Each of the two big task progress reporting works fine with this setup. 此设置可以很好地完成两个大任务进度报告。

My problem is that I want to execute these two big tasks in parallel, and I want to track their progress as a whole. 我的问题是我想并行执行这两个大任务,并且希望整体跟踪它们的进度。 Is there any way to do this? 有什么办法吗?

I have tried creating a NSProgress object at the outer level to wrap the two big task's NSProgress (so three NSProgress levels in total), but the problem is that the two tasks "fight" when updating progress. 我尝试在外层创建一个NSProgress对象来包装两个大任务的NSProgress (因此总共三个NSProgress级别),但是问题是更新进度时两个任务“打架”了。 That is, one task could execute becomeCurrentWithPendingUnitCount: and then the other task could execute resignCurrent which causes an exception (since the second task's NSProgress is not current). 也就是说,一个任务可以执行becomeCurrentWithPendingUnitCount: ,然后另一个任务可以执行resignCurrent ,这会导致异常(因为第二个任务的NSProgress不是当前的)。

Making the two tasks sequential instead of parallel fixes the issue, but I really would like to execute them at the same time. 使两个任务依次而不是并行解决了这个问题,但是我真的很想同时执行它们。 Any ideas? 有任何想法吗?

Yes you can run 2 async operations in parallel with an NSProgress . 是的,您可以与NSProgress并行运行2个异步操作。 Here's a snippet of what I do. 这是我所做的摘要。

   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.
}

You have to make sure your 2 tasks are asynchronous. 您必须确保您的2个任务是异步的。 That means the resign call is called right away, even though the task is still executing. 这意味着即使任务仍在执行,也将立即调用辞职呼叫。 When I tried to resign in the completion of an async task, I got that error due to the fact that the NSProgress had already been resigned elsewhere. 当我尝试在完成异步任务时辞职时,由于NSProgress已经在其他地方辞职,导致出现该错误。 So Like my example Task1 and Task2 are also async and also contain child NSProgresses in them. 因此,就像我的示例一样,Task1和Task2也异步,并且它们中还包含子NSProgresses。 You more or less want to resign the current progress right after kicking off the async task and not waiting until it is done. 您或多或少希望在启动异步任务之后立即辞职,而不要等到完成后再辞职。

As a side note I like to use 100 units as the pending so I can think of each task as a percentage of it. 附带说明一下,我喜欢使用100个单位作为待处理单位,因此我可以将每个任务视为百分比。 You could also use byte count for units pending but I tend to do that at the lower child processes where actual data processing happens and not in the parent process. 您还可以将字节数用于待处理的单元,但我倾向于在较低的子进程中执行此操作,在该子进程中实际发生数据处理,而不是在父进程中。 Like my example I dispatch an async task for uploading all new User objects to an API and a process for uploading all new user photos. 像我的示例一样,我调度了一个异步任务,该任务将所有新的User对象上载到API,并调度了一个过程,用于上载所有新的用户照片。 The photo task counts the byte size of the photo and uses that for updating the child process but the parent task is about 40% of the main task and that's why I use percentages because some times you don't know the aggregated byte count if you have complex multiple object processes. 照片任务会计算照片的字节大小,并将其用于更新子进程,但父任务约占主任务的40%,这就是为什么我使用百分比,因为有时您不知道汇总的字节数,如果您具有复杂的多对象流程。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM