异步网络+线程问题

时间:2010-06-04 23:47:53

标签: cocoa networking multithreading

我启动网络请求,假设不需要登录凭据来与目标服务器通信。如果需要它们,那么我会收到身份验证质询,此时我会显示一个请求来自用户的凭据的视图。提供它们后,我使用这些凭据重新启动网络请求。

只要我一次只做一个请求,这一切都很好,很花哨。但我不是,通常。

当两个请求都被启动时,我得到第一个挑战,并提示提示(使用-presentModalViewController :)。然后第二个挑战进来了。当它试图显示第二个提示时我崩溃了。

我将大部分内容包装在@synchronized()块中,但这没有任何效果,因为这些委托方法都在同一个(主)线程上调用。文档说,委托方法是在启动连接的同一线程上调用的。好的,没问题;我将编写一个使用-performSelectorInBackground:

在后台线程上运行的方法
NSURLConnection *connection = [[NSURLConnection alloc] 
                               initWithRequest:request 
                                      delegate:self
                              startImmediately:NO];
[connections addObject:connection];
[self performSelectorInBackground:@selector(startConnection:) 
                       withObject:connection];
[connection release];

- (void)startConnection:(NSURLConnection *)connection {
   NSAutoreleasePool *pool = [NSAutoreleasePool new];
   [connection scheduleInRunLoop:[NSRunLoop currentRunLoop] 
                         forMode:NSDefaultRunLoopMode];
   [connection start];
   [pool drain];
}

应将每个网络请求及其回调放在自己的线程上,然后我的@synchronized()块才会生效。

-initWithRequest的文档:... state“发送给委托的消息将在调用此方法的线程上发送。默认情况下,为了使连接正常工作,调用线程的运行循环必须在默认运行中运行循环模式。“好的,我正在那样做。

他们还说“如果你传递NO [for startImmediately] ,你必须在启动之前在运行循环中安排连接。”好的,我也是这样做的。

此外,NSRunLoop状态的文档“每个NSThread对象,包括应用程序的主线程,都根据需要自动为其创建一个NSRunLoop对象。如果需要访问当前线程的运行循环,可以使用类方法currentRunLoop“。我假设这适用于调用-performSelectorInBackground创建的后台线程...(当我在-startConnection:方法中执行'po [NSClassFromString(@“NSRunLoop”)currentRunLoop]时,似乎就是这种情况) )。

确实正在调用-startConnection:方法。但是在开始连接之后,我现在永远不会在其上获得任何回调。没有-connectionDid ...委托方法。 (我甚至尝试显式启动线程的运行循环,但这没有任何区别;我之前使用过这样的线程,而且我从来没有必须手动启动运行循环 - 但我现在正在抓住吸管。 ..)

我想我已经想出了一个解决方法,这样我一次只能处理一个请求,但它很笨拙,而且我想以正确的方式做到这一点。但是,我在这里错过了什么?

谢谢! 好色

1 个答案:

答案 0 :(得分:0)

是否达到了[pool drain];行?我猜它是。在此之后,-startConnection方法退出,此时后台线程完成并销毁。这可能不是你想要的......

你必须运行runloop。你说你这样做了,没有任何区别。这意味着你做错了。阅读Runloop section in the Threaded Programming Guide(最好转到正确的文档,而不是听取我的意见)。请注意,像-performSelectorInBackground这样有用的方法可能会使多线程看起来很吸引人,但很难。

另外,你是什么意思

  

'包装在@synchronized()块中,   但这没有效果,因为这些   委托方法都被调用   在同一(主要)线程'

@synchronized()将在主线程上执行与在后台线程上相同的操作..您认为它有什么作用?