在Objective-C中连续执行循环迭代

时间:2015-02-13 20:10:03

标签: ios objective-c multithreading grand-central-dispatch

我需要创建一个循环,迭代应该在一个线程中执行,并且一个接一个地连续执行。 我试图在dispatch_sync和我的自定义序列队列myQueue

的循环中将每个操作添加到队列中
dispatch_queue_t myQueue = dispatch_queue_create("samplequeue", NULL);
void (^myBlock)() = ^{
  //a few seconds long operation
};

for (int i = 0; i < 10; ++i) {
    dispatch_sync(myQueue, myBlock);
}

但是不起作用。 我也尝试了dispatch_apply但是没有用。

我还尝试在没有循环的情况下向队列中添加操作。

dispatch_sync(myQueue, myBlock);
dispatch_sync(myQueue, myBlock);
dispatch_sync(myQueue, myBlock);

但没有任何作用......那么,为什么我不能这样做呢?

我需要它用于记忆经济。每个操作都需要一些内存,完成后会保存结果。因此,下一个操作可以重用此内存。  当我手动运行它们(每次上次操作完成时点击屏幕上的按钮)我的应用程序需要一点内存,但是当我使用循环时,它们会一起运行并占用大量内存。

任何人都可以帮我解决这个案子吗?也许我应该使用@synchronize()或NSOperation&amp; NSOperationQueue,还是NSLock?

3 个答案:

答案 0 :(得分:2)

我有一个更复杂的答案using barriers,但后来我意识到了。

dispatch_queue_t myQueue = dispatch_queue_create("samplequeue", NULL);
void (^myBlock)() = ^{
    for (int i = 0; i < 10; ++i) {
        //a few seconds long operation
    }
};

dispatch_async(myQueue, myBlock);

答案 1 :(得分:2)

这显然是你真正的问题:

  

我需要它用于记忆经济。每个操作都需要一些内存,完成后会保存结果。因此,下一个操作可以重用此内存。当我手动运行它们(每次上次操作完成时点击屏幕上的按钮)我的应用程序需要一点内存,但是当我使用循环时,它们会一起运行并占用大量内存。

您在此处描述的问题听起来像是自动释放池问题。每个操作分配一些对象并自动释放它们。默认情况下,自动释放池在运行循环的“结束”处(在运行循环查找要分派的下一个事件之前)耗尽(并且可以释放对象)。因此,如果在单次传递运行循环期间执行大量操作,则每个操作都将分配和自动释放对象,并且在所有操作完成之前,这些对象都不会被释放。

你可以像这样显式地消耗运行循环:

for (int i = 0; i < 10; ++i) {
    @autoreleasepool {
        // a few seconds long operation
    }
};

您试图使用dispatch_sync,但队列不一定在新的自动释放池中运行阻止。实际上,dispatch_sync尝试在可能的情况下立即在调用线程上运行块。这就是你的情况。 (队列不是线程!只有“主”队列关心它使用的线程;其他队列将在任何线程上运行它们的块。)

如果操作真的是几秒钟,那么你肯定应该在后台线程上运行它,而不是主线程。您使用dispatch_async在后​​台线程上运行块。如果您想在所有操作完成后执行某些操作,请排队最后一个块以执行额外操作:

dispatch_queue_t myQueue = dispatch_queue_create("samplequeue", NULL);

for (int i = 0; i < 10; ++i) {
    dispatch_async(myQueue, ^{
        @autoreleasepool {
            //a few seconds long operation
        }
    });
}

dispatch_async(myQueue, ^{
    // code to run after all long operations complete
});

dispatch_queue_release();

// Execution continues here on calling thread IMMEDIATELY, while operations
// run on a background thread.

答案 2 :(得分:0)

现在回答这个问题为时已晚,但最近我面临完全相同的问题,我在NSArray上创建类别(NSArray + TaskLoop)以连续执行迭代

你可以从这里下载 https://github.com/SunilSpaceo/DemoTaskLoop

要按顺序执行迭代,您应该使用

[array enumerateTaskSequentially:^(....];

将您的迭代置于块中并调用 完成该迭代后完成(nil)

不要忘记调用完成块,否则它不会进入下一次迭代