【问题标题】:NSRunLoop runMode:beforeDate: doesn't waitNSRunLoop runMode:beforeDate: 不等待
【发布时间】:2016-02-01 04:55:43
【问题描述】:

正如标题所说,NSRunLoop 的 runMode:beforeDate: 不会等待。我应该怎么做才能让线程等待 NSRunLoop。

我正在后台线程上运行一个方法:

[self performSelectorInBackground:@selector(performOperation:) withObject:nil];


- (void)performSynchronousOperation:(operation *)operation
{
    operationComplete = NO;

    // Now wait for response
    NSRunLoop *theRL = [NSRunLoop currentRunLoop];

    while (!operationComplete && [theRL runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]]);

    return;
}

后台线程不会在 while 循环中等待。我有什么遗漏吗?

【问题讨论】:

    标签: ios objective-c multithreading


    【解决方案1】:

    几个观察:

    1. 为了让运行循环保持活跃,您需要为其添加一个源。例如,您可以这样做:

      [[NSRunLoop currentRunLoop] addPort:[NSMachPort port] forMode:NSDefaultRunLoopMode];
      

      不幸的是,这也将阻止runMode 完成,直到端口从运行循环中删除。因此,您要么必须在设置operationComplete 时删除此源。或者不要使用这个runMode 方法(例如,可能使用CFRunLoopRunInMode Core Foundation 函数,如Threading Programming Guide: Run Loops 中的清单3-2 所示)。

    2. 我对在您的方法名称中使用“同步”感到困惑。如果你在后台线程上做一些同步的事情,那么你不需要做任何这些运行循环的东西。只有在后台线程上执行异步任务时才需要这样做,即使那样,通常也有更好的方法。

    也许您可以通过代码示例解释您要解决的问题,我们可以提供更多帮助。

    有关其他见解,请参阅 Rob Mayoff's answer

    【讨论】:

    • 是的,我正在尝试在后台线程中执行异步网络操作。但是线程在while循环中等待下面的实现,我不明白为什么。 - (void) performSynchronousOperation { [operation start]; // 网络操作将开始(操作是一个类,其基类是 NSOperation 并实现了它的 'main' 方法) // 现在等待响应 NSRunLoop *theRL = [NSRunLoop currentRunLoop]; while (!operationComplete && [theRL runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]]); // thread waits here. dont know why? }
    • 如果你正在做一个异步网络操作,你只需要在后台线程上调度NSURLConnection 时通过这个后台线程愚蠢。但无论如何现在都已弃用,您应该使用NSURLSession,在这种情况下,您可以完全删除这个后台线程代码。如果您将其包装在NSOperation 中,那么您应该继承NSOperation 并使其成为异步操作,然后享受操作依赖关系,maxConcurrentOperationCount 等。请参阅stackoverflow.com/a/21205992/1271826 的后半部分以获取示例如何做到这一点。
    • 如果您已将端口添加到NSRunLoop,这将阻止后台线程的运行循环退出,但也会阻止runMode:beforeDate: 终止。这就是为什么我建议使用CFRunLoopRunInMode。但这一点没有实际意义,因为无论如何,当网络请求正在进行时,你真的不应该在运行循环中旋转。请参阅我之前的评论。
    【解决方案2】:

    Apple API docs 对此方法的评价如下:

    如果没有输入源或计时器附加到运行循环,则此方法立即退出并返回 false

    这就是它不等待的原因。不知道你想在这里实现什么。但是,如果您想做这样的等待,我建议您使用其他方式,例如dispatch_semaphore

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-12-09
      • 1970-01-01
      • 1970-01-01
      • 2018-05-04
      • 2020-05-09
      • 2021-09-15
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多