等待许多异步调用来执行回调 [英] Wait for many asynchronous calls to perform callback

查看:190
本文介绍了等待许多异步调用来执行回调的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想将一些数据与Web服务同步。对于每个项目,我必须进行异步调用。

I want to synchronize some data with a web service. For each item I have to make a asynchronous call.

我希望在每个项目同步时调用完成块。对于每个项目,我能够执行完成块。现在,我不知道如何做到这一点。

I want to have a completion block witch is called, when each item was synchronized. For each item I am able to perform a completion block. Now, I don't know a good way how to do it.

这是界面:

-(void) synchronizeItemsOnComplete:(CompleteBlock) block {
    NSArray* items = // get items
    for (int i = 0, n = [items count]; i < n; i++) {
       [self synchronizeItem:[items objectAtIndex:i] onComplete:^{
          // What do do here?
       }];
    }
    // And/or here?
}

-(void) synchronizeItemOnComplete:(CompleteBlock) block {
    // do something
    block();
}

我如何等待同步然后执行阻止?

How can I wait for the synchronization and then perform the block?

我尝试过这样的事情:

NSArray* items = // get items

__block int countOfItemsUntilDone = [items count];

for (int i = 0, n = countOfItemsUntilDone; i < n; i++) {
    [self synchronizeItem:[items objectAtIndex:i] onComplete:^{
        countOfItemsUntilDone--;
    }];
}

dispatch_queue_t queue = dispatch_queue_create("wait for syncing", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(queue, ^{
    while (countOfItemsUntilDone > 0) {
        usleep(1000); // wait a little bit
    }
    block();
});
dispatch_release(queue);

但我认为这是一个非常糟糕的方式。有什么想法?

But I think this is a quite bad way. Any ideas?

推荐答案

不是在等待计数器等于零的循环中旋转,而是每次减量时检查计数器值然后,当它达到零时触发一个事件。

Instead of spinning in a loop waiting for the counter to equal zero, check the counter value each time you decrement it, then fire an event when it reaches zero.

 -(void) synchronizeItemsOnComplete:(CompleteBlock) block {
    NSArray* items = // get items
    __block NSUInteger remaining = [items count];

    for (ItemClass* item in items) {
       [self synchronizeItemImage:item onComplete:^{
            --remaining;
            if (remaining == 0) {
                block();
            }
       }];
    }
 }

要解释为什么感觉不对,有两件事你在这里做的是你应该做的永远或者很少:

To explain why it feels wrong, there are two things you're doing here that you should do either never or rarely:


  • 使用背景队列。这很难并容易出错。如果没有阅读关于编写并发代码的 lot ,请不要这样做。如果操作会阻塞大量时间(例如,从磁盘读取文件或执行密集计算),您也只需要这样做。除非你有充分的理由(例如,可衡量的性能问题),否则不要假设你需要这样做。

  • Using background queues. This is difficult and bug-prone. Don't do it without reading up a lot about writing concurrent code. You also only really need to do this if an operation blocks for a substantial amount of time (eg., to read a file from disk, or perform an intensive calculation). Don't assume you need to do it unless you have a good reason (eg., a measurable performance problem).

在循环中旋转,检查变量变量和调用睡眠。你应该从不这样做。

Spinning in a loop, checking a variable for changes and calling sleep. You should never do this.

另外,如果你在循环元素在一个数组中, for ... in 语法在每个索引上调用objectAtIndex:更好(并且可能更有效)。

Also, if you're looping over the elements in an array, the for ... in syntax is much nicer (and potentially more efficient) calling objectAtIndex: on each index.

这篇关于等待许多异步调用来执行回调的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆