如何在objective-c中等待执行任务

时间:2014-05-30 15:51:39

标签: objective-c objective-c-blocks grand-central-dispatch

我有一个问题如何等待执行某些方法中的几个任务,即使该方法在不同的线程中被调用几次;

例如:

当我打电话给方法时:

1:

2:

我希望看到以下内容:

1: 第1步,第2步;

2: 第1步,第2步;

但我经常看到以下内容:

1: 2: 第1步,第1步, 第2步,第2步,

请参阅下面的代码,或许有助于更好地理解问题;

//many times per second
- (void)update:(UpdateObjectClass *)updateObject {    
    //step 1:
    //update common data(for example array)
    //long process(about 1-2 seconds)
    [self updateData:updateObject];

    //step 2:
    //update table
    [self updateTableView];
}

我尝试使用dispatch_barrier_async,但我不明白如何以正确的方式使用它;

感谢您的帮助;)

3 个答案:

答案 0 :(得分:3)

我借用@ remus的答案。

假设在对象的同一个实例(而不是一大堆对象)上调用-[update:],您可以使用@synchronized强制执行您的代码只执行一次 - 一个时间。

dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void){

    @synchronized(self) {
        // Run your updates
        // [self updateData:updateObject];

        dispatch_async(dispatch_get_main_queue(), ^(void){

            // Async thread callback:
            [self updateTableView];
        });
    }
});

然而

我准备好了,并猜测你需要同步执行此代码的原因是因为你的-[updateData:]方法正在做线程安全的事情,例如修改NSMutableDictionaryNSMutableArray。如果是这种情况,您应该在可变对象本身上使用@synchronized技巧。

如果时间不长,我强烈建议您将代码发布到-[updateData:]

答案 1 :(得分:1)

您正试图在错误的级别解决问题,并且问题中的信息不太可能提供任何解决方案。

根据报告的输出,我们知道updateDataupdateTableView是异步的并且使用一个或更多任务。我们不知道他们使用什么队列,他们产生了多少任务,他们是否有一个在子任务之前没有完成的外部任务等等。

如果查看标准API,您会看到异步方法通常需要完成块。在内部,这样的方法可以在多个队列上使用多个任务,但是它们被编写为使得所有这些任务在它们调用完成块之前完成。你可以重新设计updateData所以它需要一个完成块(你将用它来调用updateTableView)吗?

完成块模型本身并不能解决您根据其他任务的完成来安排任务所需的所有方法,还有其他机制,包括:串行队列,调度组和调度障碍。 / p>

串行队列可以在完成之前添加到队列的所有其他任务后调度任务。调度组允许将在多个队列上调度的多个任务标记为属于一个组,并且计划在组中的所有任务完成后运行的任务。调度障碍使得可以在并发队列上调度的所有先前任务之后调度任务。

您需要研究这些方法,然后根据您的需要将适当的方法嵌入到updateDataupdateTableView和最终update本身的设计中。您可以使用自下而上的方法,基本上与您的问题尝试相反。从最低级别开始,询问一个或多个任务是否应该是一个组,具有障碍,是否顺序,并且可能需要完成块。然后向上移动。

可能不是你希望的答案! HTH

答案 2 :(得分:0)

考虑使用dispatch_async运行数组更新,然后更新tableView。您可以在单个方法中执行此操作:

dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void){
    // Run your updates
    // [self updateData:updateObject];

    dispatch_async(dispatch_get_main_queue(), ^(void){

        // Async thread callback:
        [self updateTableView];
    });
});

修改

我考虑修改您的updateData方法以在异步队列中运行;完成后,直接从该方法调用[self updateTableView];。如果时间不长,您可以在问题中添加[self updateData:updateObject]代码(或部分内容)吗?