我需要创建一个循环,迭代应该在一个线程中执行,并且一个接一个地连续执行。
我试图在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?
答案 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)
不要忘记调用完成块,否则它不会进入下一次迭代