2016-02-01 35 views
2

由于标题说NSRunLoop的runMode:beforeDate:不等。我应该怎么做才能让线程等待NSRunLoop。NSRunLoop runMode:beforeDate:不要等待

我运行在后台线程的方法:

[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循环等待。有什么我失踪?

回答

2

一对夫妇的意见:

  1. 为了保持运行循环活着,你有一个源添加到它。例如,你可以这样做:

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

    不幸的是,这也将保持runMode无法完成,直到端口从运行循环中去除。因此,您在设置operationComplete时必须删除此源。或者不要使用这个runMode方法(例如可能使用核心基础功能,如Threading Programming Guide: Run Loops的清单3-2所示)。

  2. 我很困惑在您的方法名称中使用“synchronous”。如果你在后台线程上做了一些同步操作,那么你不需要做任何这种runloop的东西。这只是在后台线程上执行异步任务时才需要,而且即使这样,通常也有更好的方法。

也许你能解释一下你想与你的代码示例来解决什么问题,我们可以帮助更多。

查看Rob Mayoff's answer了解其他见解。

+0

是的,我想在后台线程中执行异步网络操作。但线程在while循环等待下面的实现,我不明白为什么。 ' - (无效)performSynchronousOperation {' '[操作开始]; //'网络操作将开始(操作是一个类,其基类是的NSOperation并实现它的“主”方法) //现在等待回复#1:NSRunLoop * theRL = [NSRunLoop currentRunLoop];' 'while(!operationComplete && [theRL runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]]); //线程在这里等待。不知道为什么?' '}' –

+0

如果你在做一个异步网络操作,如果在后台线程上调度NSURLConnection,你只需要经历这个后台线程的愚蠢行为。但是现在已经废弃了,你应该使用'NSURLSession',在这种情况下你可以完全去掉这个后台线程代码。如果你将它包装在一个'NSOperation'中,那么你应该子类NSOperation并使其成为一个异步操作,然后享受操作依赖关系,maxConcurrentOperationCount等。参见http://stackoverflow.com的后半部分/ a/21205992/1271826举例说明如何做到这一点。 – Rob

+0

如果你已经添加了端口到'NSRunLoop',这将保持后台线程的运行循环不会退出,但是也会阻止'runMode:beforeDate:'终止。这就是为什么我建议'CFRunLoopRunInMode'。但是这一点是没有意义的,因为无论如何,当网络请求正在进行时,你确实不应该在运行循环中旋转。看到我以前的评论。 – Rob

1

以下是Apple API docs说一下这个方法:

如果没有输入源或定时器连接到运行循环,此方法立即退出并返回false

这就是为什么它不等待。不知道你想在这里实现什么。但是,如果你想做这样的等待事情,我推荐使用其他方式,如dispatch_semaphore