在对象被释放后刚刚启动的线程

时间:2012-06-15 07:54:55

标签: iphone ios multithreading

我的iOS应用程序中存在这种情况。

我正在向web api发出请求,我正在后台线程中这样做。我有一个名为Service的类,它有这个方法:

- (void)searchForRoutesFrom:(NSNumber *)startStationId
                         to:(NSNumber *)endStationId
                   delegate:(id<WAMSServiceDelegate>)delegateOrNil
{
    RouteSearchRequest *request = [[RouteSearchRequest alloc] init];
    ...request populate ...
    [NSThread detachNewThreadSelector:@selector(searchForRoutesInTheBackground:) 
                             toTarget:self withObject:request];
}

- (void)searchForRoutesInTheBackground:(RouteSearchRequest *)request
{
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    ...make the request and call back...
}

这很好用,但是如果用户决定离开View(使用此服务),就在线程启动之前,就会释放Service对象。当线程启动时,它将尝试调用searchForRoutesInTheBackground方法,我的应用程序将崩溃。

我可以使用哪些其他方法来运行此线程并处理正在释放的调用对象。

3 个答案:

答案 0 :(得分:0)

你可以在启动线程之前retain调用对象,并在处理结束时(就在返回之前)释放它。

 - (void)searchForRoutesFrom:(NSNumber *)startStationId
                     to:(NSNumber *)endStationId
               delegate:(id<WAMSServiceDelegate>)delegateOrNil
{
RouteSearchRequest *request = [[RouteSearchRequest alloc] init];
...request populate ...

[self retain];
[NSThread detachNewThreadSelector:@selector(searchForRoutesInTheBackground:) 
                         toTarget:self withObject:request];
}

- (void)searchForRoutesInTheBackground:(RouteSearchRequest *)request
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
...make the request and call back...

[self release];
}

如果您使用了块,那将自动为您完成,但保留/释放很容易管理这种情况。

答案 1 :(得分:0)

由于您的逻辑信息不足,我不确定是否会根据您的情况正确回答您,但我以不同的方式处理这些情况。我所做的是创建单独的类(MVC模型),用于通过启动请求和处理回调的方法与Web服务进行通信。当回调执行时,有不同的场景 - (使用CoreData持久化结果,我的UI捕获此事件并更新(如果可见),或者将块作为参数传递给发出请求的方法,并在回调中调用并且块被执行,并且通常块以if(!self.view.window) return;开始,这意味着如果当前视图不可见则不会发生任何事情)。但在这两种情况下,我的请求和回调完全独立于UI,因此不会出现像你这样的问题。

答案 2 :(得分:0)

  

但是如果用户决定离开View(使用此服务),则只需   在线程启动之前,将释放Service对象。什么时候   线程启动它将尝试并调用   searchForRoutesInTheBackground方法和我的应用程序将崩溃。

这是不可能的。请参阅documentation for +detachNewThreadSelector:toTarget:withObject:。它说

  

在执行分离线程期间保留对象aTarget和anArgument,然后释放。

这意味着在您致电detachNewThreadSelector:toTarget:withObject:时会保留该信息。因此,如果该对象在那一刻有效,它将在新线程完成执行之前有效。

如果发生了不好的事情,你必须在其他地方做错的内存管理。例如1)在调用detachNewThreadSelector:toTarget:withObject:的时间之前,对象已经被释放,或者2)你在不应该的地方过度释放对象。