performSelector:OnThread:waitUntilDone不会一直执行选择器

问题描述:

我有一个应用程序,其网络活动在其单独的线程中完成(并且网络线程不断从服务器获取数据并更新显示 - 显示调用已完成回到主线程)。当用户注销时,主线程调用上的网线断开方法如下:performSelector:OnThread:waitUntilDone不会一直执行选择器

[self performSelector:@selector(disconnectWithErrorOnNetworkThread:) onThread:nThread withObject:e waitUntilDone:YES]; 

这个选择被调用的大部分时间,一切工作正常。然而,这个调用永远不会返回(换句话说,选择器永远不会执行)并且线程和应用程序挂起的时候(可能是十次中的两次)。任何人都知道为什么performSelector行为不正常?

请注意,我需要等到呼叫得到执行,这就是为什么waitUntilDone为YES,因此将其更改为NO不适用于我。此外,网络线程的运行循环正在运行(我在创建线程时明确地启动它)。

请注意,由于数据传输的连续性,我需要明确使用NSThreads而不是GCD或Operations队列。

+1

当断开连接失败时,您是否暂停了调试程序以查看哪些代码正在运行?它可能正处于数据传输的中间,因此直到下一次运行循环时才会取消该数据块的发送或接收。 – Joe

+0

Joe,小数据交换中收到数据,因此一旦当前数据传输结束,就应该调用选择器。运行循环应在完成当前数据传输后安排断开连接。这大概是80%的时间,而不是所有的时间。至于调试器,它会在disconnectWithErrorOnNetworkThread调用中暂停,然后等待。也实际disconnectWithErrorOnNetworkThread方法永远不会进入(我有一个NSLog在该方法的开始,永远不会被调用)。 –

+2

我认为@Joe询问目标线程('nThread')发生了什么,而不是在调用线程中发生了什么。如果目标线程永远不会回到它的主循环,它永远不会为您执行选择器。 – abarnert

那先挂,如果:

  • 它正试图在同一个线程的方法是从

  • 调用调用以执行选择执行一个选择就是一个线程从同步调用有人提出,引发了执行选择

当你的程序被挂起,看看所有线程的回溯。

请注意,当实现任何类型的网络并发时,通常真的很差有从网络代码到UI层或其他线程的同步调用。网络线程需要非常灵敏,因此,就像阻塞主线程是不好的,任何可以阻塞网络线程的东西都是不好的。

还要注意,一些带回调的API不一定能保证回调将被传递到哪个线程。如上所述,这可能会导致间歇性锁定。

最后,不要做任何活动的轮询。你的网络线程应该完全静止,除非有事件发生。任何类型的循环轮询对于电池寿命和响应都是不利的。

+0

你说如果“它试图在调用方法的同一个线程上执行一个选择器”,就会发生挂起。但是文档说:“如果当前线程和目标线程相同,并且您为此参数指定'YES',则选择器立即在当前线程上执行”,根据我的经验,我发现这是真的。 –

+0

是正确的,但并非所有的同步调用机制都可以保护您免受这样的挂起。例如,'dispatch_sync()'。例如,当以特定模式进行调度时,您也可以挂起嵌套运行循环。 – bbum

+0

@Joe,你有第一个正确的答案,但是SO不让我把你的评论标记为答案,所以提高你的评价。 bbum:你的答案更全面,正如你猜测的那样,主线程阻塞了网络线程(开始时这真是个坏主意),反之亦然。这是一个简单的修复。感谢你们两位的帮助! –