【问题标题】:Performing loop iterations serially in Objective-C在 Objective-C 中连续执行循环迭代
【发布时间】:2015-04-14 23:41:16
【问题描述】:

我需要创建一个循环,该循环应该在一个线程中一个接一个地依次执行。 我尝试使用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 & NSOperationQueue 或 NSLock 之类的东西?

【问题讨论】:

  • Ummm..."concurrently" 表示它们都同时运行。并发操作可能对某些东西具有串行访问权限,这会一次发生一个。
  • 您是否考虑过在目标线程上编写一个循环?
  • Hot Licks,你能写一个代码示例吗?

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


【解决方案1】:

我有一个更复杂的答案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);

【讨论】:

    【解决方案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.
    

    【讨论】:

      【解决方案3】:

      现在回答这个问题为时已晚,但最近我遇到了完全相同的问题,我在 NSArray 上创建了 category(NSArray+TaskLoop) 以串行和并行执行迭代

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

      要连续执行迭代,您应该使用

      [数组 enumerateTaskSequentially:^(.... ];

      将您的迭代放入块中并调用 完成该迭代时的完成(无)

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2020-01-28
        • 2012-09-02
        • 1970-01-01
        • 1970-01-01
        • 2021-04-21
        • 2021-04-13
        • 2016-02-20
        相关资源
        最近更新 更多