1

我正在尝试同步对服务名称进行 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
}

只要我的代码在 resolve 事件出现后继续运行一秒钟左右,我就会很高兴。

实际发生的事情是解析发生得很快,我看到 netServiceDidResolveAddress() 中的代码完成了,但是在控制从 runUntilDate 返回之前一直有一个不受欢迎的 5-6 秒等待,我看到“...(运行后循环)调试语句。

我环顾了几个留言板,看到了类似的问题,但他们的解决方案(如使用 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 秒延迟,我将不胜感激。

4

2 回答 2

1

你真的不应该这样做。网络解析是异步的有一个很好的理由:执行解析可能需要很长时间,而且在大多数情况下,您不希望在此期间阻塞线程。如果你在主线程上做解析,你真的不想同步做。在 Mac OS X 上,阻塞主线程的长时间运行的操作将导致旋转的沙滩球。在 iOS 上,看门狗可能会完全杀死您的应用程序。

API 是异步的,以鼓励您正确使用它。不要试图与之抗争。

由于您没有解释为什么要尝试同步执行此操作,因此我无能为力,但请记住 Cocoa 是事件驱动的。将您的同步步骤分解为状态,并让每个阶段中来自 Cocoa 的回调驱动您的状态机前进。它看起来不像逐行程序函数那么好,但它会让你的 UI 保持响应并避免丑陋的变通方法。

于 2011-07-11T20:20:41.150 回答
0

只需删除CFRunLoopStop它,它应该可以正常工作。停止NSRunLoop将停止有关 this 的任何其他事件NSThread。我做了同样的事情(没有停止 RunLoop)来同步解决一些NSNetServices问题,它工作得很好。

于 2013-08-06T13:31:35.840 回答