使用NSNetService进行同步Bonjour解析(为什么从runloop返回控制需要这么长时间?)

时间:2011-07-11 14:02:46

标签: cocoa-touch bonjour synchronous nsrunloop nsnetservice

我正在尝试同步执行服务名称的Bonjour解析,所以我试图弄清楚如何正确等待NSNetService的netServiceDidResolveAddress()调用。

我的代码如下所示:

service = [[NSNetService alloc] initWithDomain:@"local." type:@"_myservice._tcp" name:[self name]];
[service retain];
[service setDelegate:self];
waitingOnResolution = true;
[service resolveWithTimeout:5.0];

for (int i=0;i<5;i++) {
    DebugLog(@"resolve: resolve iteraton %u\n", i);
    [[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:1]]; // run loop for one second
    DebugLog(@"resolve: resolve iteraton %u (after run loop)\n", i);
    if (!waitingOnResolution) break;   
}

// continue processing...

这是我处理解决方案成功的函数:

- (void)netServiceDidResolveAddress:(NSNetService *)sender
{
    // do processing...
    waitingOnResolution = false;
    CFRunLoopStop([[NSRunLoop currentRunLoop] getCFRunLoop]); // has no effect
}

只要我的代码在解决事件发生后继续运行一秒左右,我会很高兴。

实际发生的是解决方法很快就会发生,我看到netServiceDidResolveAddress()中的代码完成了,但是一直有一个不合需要的5-6秒等待,直到控制从runUntilDate返回并且我看到“... (运行循环后)调试语句。

我环顾了几个留言板并看到了类似的问题,但他们的解决方案(如使用CFRunLoopStop)似乎没有任何效果。

以下是我收到的日志记录示例:

2011-07-11 09:38:07.267 MyProgram[1822:707] resolve: resolve iteraton 0
2011-07-11 09:38:07.299 MyProgram[1822:707] netService: netServiceDidResolveAddress function ended

[5+ second delay]

2011-07-11 09:38:12.907 MyProgram[1822:707] resolve: resolve iteraton 0 (after run loop)

如果有人可以告诉我使用NSNetService解析器获得同步结果的不同方法,或者重构我的runloop相关代码以避免这种(看似操作系统创建的)5-6秒延迟,我将不胜感激。

2 个答案:

答案 0 :(得分:1)

你真的不应该这样做。网络解析是异步的,原因很简单:可能需要很长时间才能执行解析,在大多数情况下,您不希望在一段时间内阻止线程。如果您在主线程上执行解析,则 实际上不 想要同步执行此操作。在Mac OS X上,阻止主线程的长时间运行操作将导致旋转沙滩球。在iOS上,看门狗可能完全杀死你的应用程序。

API是异步的,鼓励您正确使用它。不要试图打击它。

既然你没有解释为什么你试图同步这样做,我不能帮助更多,但请记住,Cocoa是事件驱动的。将您的同步步骤分解为状态,并让每个阶段的Cocoa回调驱动您的状态机前进。它看起来不像逐行程序功能那么好,但它会保持你的UI响应并避免丑陋的变通方法。

答案 1 :(得分:0)

只需删除CFRunLoopStop即可。停止NSRunLoop将停止此NSThread上的任何其他活动。我做了同样的事情(没有停止RunLoop)同步解析一些NSNetServices并且它工作正常。