代码之家  ›  专栏  ›  技术社区  ›  randallmeadows

异步网络+线程问题

  •  1
  • randallmeadows  · 技术社区  · 16 年前

    我启动了一个网络请求,假设与目标服务器对话不需要登录凭据。如果它们是必需的,那么我将收到一个身份验证挑战,此时我将显示一个视图,请求用户提供所述凭证。当它们被提供时,我使用这些凭据重新启动网络请求。

    只要我一次只做一个请求,那就太好了。但我通常不是。

    当两个请求都启动时,我将得到第一个挑战,并显示提示(使用-presentmodalview控制器:)。接下来是第二个挑战。当它试图显示第二个提示时,我崩溃了。

    我将此方法的大部分包装在@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的文档:…状态“将在调用此方法的线程上向委托发送消息。默认情况下,为了使连接正常工作,调用线程的运行循环必须在默认的运行循环模式下运行。“好的,我正在这样做。

    他们还说“如果你通过了不” [立即开始] ,在启动连接之前,必须在运行循环中调度连接。“好的,我也在这样做。

    此外,每个nsthread对象(包括应用程序的主线程)的nsrloop状态文档都根据需要自动为其创建了一个nsrloop对象。如果您需要访问当前线程的run loop,可以使用类方法current run loop来实现。“我假设这适用于由call-performselectorinbackground创建的后台线程…(当我在-startConnection:方法中执行'po[nsclassFromstring(@“nsrlundop”)currentRunLoop]'时,情况确实如此)。

    确实正在调用-StartConnection:方法。但是在开始连接之后,我现在再也没有 任何 回电。没有-connectiondid__delegate方法。(我甚至尝试显式地启动线程的运行循环,但这没什么区别;我以前使用过这样的线程,而且我以前从来没有手动启动过运行循环——但现在我正在抓紧稻草…)

    我想我已经想出了一个解决方法,这样我一次只处理一个请求,但这很笨拙,我想用正确的方式来处理。但是,我在这里错过了什么?

    谢谢! 兰迪

    1 回复  |  直到 16 年前
        1
  •  0
  •   hooleyhoop    16 年前

    [pool drain]; 直线到达?我想是的。在此之后,-startconnection方法退出,此时后台线程将完成并销毁。这可能不是你想要的

    你必须运行runloop。你说你做了这件事没什么区别。这意味着你做错了。阅读 Runloop section in the Threaded Programming Guide (去看适当的医生总比听我说的好)。注意,像-performselectorinbackground这样的有用方法可能会使多线程看起来很吸引人,但这很困难。

    还有,你什么意思

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

    ?

    @synchronized()在主线程上的作用与在后台线程上的作用相同。你认为它能做什么?