【问题标题】:iOS network on background thread causes application to hang后台线程上的 iOS 网络导致应用程序挂起
【发布时间】:2012-09-19 21:01:47
【问题描述】:

我有一个为网络消息创建后台线程的应用程序。除非它连接的服务器关闭连接,否则该应用程序几乎可以完美运行。我不确定为什么会发生这种情况,但非常感谢任何建议。我已经包含了可以解决问题的代码的 sn-ps。如果有不清楚的地方或需要更多细节,请告诉我。

- (void)stream:(NSStream *)stream handleEvent:(NSStreamEvent)eventCode {
switch(eventCode) {
    case NSStreamEventErrorOccurred:
        {
            NSLog(@"NSStreamEventErrorOccurred");

            [self Disconnect:self];
        }
    }
}

- (void)Disconnect:(id)sender {
    [self performSelector:@selector(closeThread) onThread:[[self class]networkThread] withObject:nil waitUntilDone:YES];

    [outputStream close];
    [outputStream removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
    [outputStream release];
    outputStream = nil;
}

+ (NSThread*)networkThread
{
    // networkThread needs to be static otherwise I get an error about a missing block type specifier
    static NSThread* networkThread = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        networkThread = [[NSThread alloc] initWithTarget:self selector:@selector(networkThreadMain:) object:nil];

        [networkThread start];
    });

    return networkThread;
}

挂断发生在返回 networkThread 行。执行该行后,应用程序似乎挂起并冻结,我无法确定原因。

提前致谢。

编辑

这里是 CloseThread 的 sn-p 代码供感兴趣的人参考

- (void)closeThread
{   
    /*if(!inputStream)
        return;

    [inputStream close];
    [inputStream removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes];
    [inputStream release];
    inputStream = nil;*/
}

【问题讨论】:

  • 您没有包括-closeThread 的实现,我怀疑这是您的实际问题。如果您只是退出线程,您的waitUntilDone:YES 很可能永远不会收到通知它已完成并死锁。
  • 我没有添加该方法的原因是因为我的断点永远不会被击中。为了确认它,我注释掉了里面的所有东西,所以这个函数是空的。如果我手动决定在 iPad GUI 上断开连接,代码可以正常工作。
  • 您是否在该线程上运行运行循环? performSelector:onThread:... 要求目标线程有一个正在处理消息的关联运行循环。
  • 我在运行循环中运行它。尝试连接时,我调用 networkThread 调用 openThread 选择器。这将执行以下操作: [inputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes]; [输入流打开];

标签: ios multithreading networking nsstream


【解决方案1】:

我建议改变:

[self performSelector:@selector(closeThread) onThread:[[self class]networkThread] withObject:nil waitUntilDone:YES];

到:

[self performSelector:@selector(closeThread) onThread:[[self class]networkThread] withObject:nil waitUntilDone:NO];

也就是说,不要等待。

【讨论】:

  • 看起来这行得通。我想等到我完成的主要原因是因为我不想确保我的对象在继续之前被删除并设置为 nil。
  • 实现这样的同步的方法(如果你真的需要它)是发送消息而不做任何其他事情。在获得消息的对象中(最终),做你想做的事,最后要么使用另一个 performSelectorOnMainThread 要么使用一个块,重新开始工作。
猜你喜欢
  • 2013-07-29
  • 2012-11-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多