取消操作时,使用ASIHTTPRequest和NSOperationQueue崩溃

时间:2010-10-22 13:44:23

标签: iphone objective-c asihttprequest nsoperationqueue

在尝试取消NSOperationQueue中的请求时,我真的很难。

在取消分配我的'引擎'对象之前,我调用了cancelOperations方法来取消队列中的所有内容,因此这将包括在飞行中的ASIHTTPRequests和排队的......例如。

Engine.m

-(void)getContent {
    if (![self queue]) {
        [self setQueue:[[[NSOperationQueue alloc] init] autorelease]];
    }

    NSURL *url = [NSURL URLWithString:@"http://allseeing-i.com"];
    ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
    [request setDelegate:self];
    [request setDidFinishSelector:@selector(requestDone:)];
    [[self queue] addOperation:request]; //queue is an NSOperationQueue
}

-(void)requestDone:(ASIHTTPRequest)*request {

    // Do something with request
}

-(void)cancelOperations {
    [self.queue cancelAllOperations];
    [self.queue waitUntilAllOperationsAreFinished];
}

-(void)dealloc {
    [super dealloc];
}

现在,在我的引擎中,我有许多getContent类型的方法,所以我的队列中有不同的请求对象。使用Engine对象时的流程为:

1)打开视图控制器 - 视图确实加载 - alloc和init Engine对象
2)//调用各种getContent样式方法来排队一些操作
3)在查看退出时,调用[engine cancelOperations];为了(a)停止飞行中的任何网络请求,并且还清空队列
4)取消分配视图,并使用引擎:[引擎释放];

如果所有请求都已在队列中完成(因为它是空的),这可以正常工作,但是如果我在请求处于活动状态时取消操作,则应用程序崩溃并出现EXC_BAD_ACCESS错误...但是在引擎成功释放后...

为什么会出现这种想法?

- EDIT-- 添加Backtrace以获取错误:

Exception Type:  EXC_BAD_ACCESS (SIGBUS)
Exception Codes: KERN_PROTECTION_FAILURE at 0x00000000b0000000
Crashed Thread:  0  Dispatch queue: com.apple.main-thread

Application Specific Information:
objc_msgSend() selector name: respondsToSelector:
iPhone Simulator 225, iPhone OS 4.1 (iPhone 4/8B117)

Thread 0 Crashed:  Dispatch queue: com.apple.main-thread
0   libobjc.A.dylib                 0x02cb5907 objc_msgSend + 27
1   CoreFoundation                  0x02ac95cd __invoking___ + 29
2   CoreFoundation                  0x02ac94a1 -[NSInvocation invoke] + 145
3   Foundation                      0x0015a3ca __NSThreadPerformPerform + 251
4   CoreFoundation                  0x02b39faf __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 15
5   CoreFoundation                  0x02a9839b __CFRunLoopDoSources0 + 571
6   CoreFoundation                  0x02a97896 __CFRunLoopRun + 470
7   CoreFoundation                  0x02a97350 CFRunLoopRunSpecific + 208
8   CoreFoundation                  0x02a97271 CFRunLoopRunInMode + 97
9   GraphicsServices                0x0320c00c GSEventRunModal + 217
10  GraphicsServices                0x0320c0d1 GSEventRun + 115
11  UIKit                           0x003e9af2 UIApplicationMain + 1160
12  Clicky                          0x000027d4 main + 102 (main.m:14)
13  Clicky                          0x00002765 start + 53

Thread 1:  Dispatch queue: com.apple.libdispatch-manager
0   libSystem.B.dylib               0x97cfe942 kevent + 10
1   libSystem.B.dylib               0x97cff05c _dispatch_mgr_invoke + 215
2   libSystem.B.dylib               0x97cfe519 _dispatch_queue_invoke + 163
3   libSystem.B.dylib               0x97cfe2be _dispatch_worker_thread2 + 240
4   libSystem.B.dylib               0x97cfdd41 _pthread_wqthread + 390
5   libSystem.B.dylib               0x97cfdb86 start_wqthread + 30

Thread 2:
0   libSystem.B.dylib               0x97cfd9d2 __workq_kernreturn + 10
1   libSystem.B.dylib               0x97cfdf68 _pthread_wqthread + 941
2   libSystem.B.dylib               0x97cfdb86 start_wqthread + 30

Thread 3:  WebThread
0   libSystem.B.dylib               0x97cd80fa mach_msg_trap + 10
1   libSystem.B.dylib               0x97cd8867 mach_msg + 68
2   CoreFoundation                  0x02b3a436 __CFRunLoopServiceMachPort + 150
3   CoreFoundation                  0x02a97984 __CFRunLoopRun + 708
4   CoreFoundation                  0x02a97350 CFRunLoopRunSpecific + 208
5   CoreFoundation                  0x02a97271 CFRunLoopRunInMode + 97
6   WebCore                         0x034093a3 RunWebThread(void*) + 483
7   libSystem.B.dylib               0x97d0581d _pthread_start + 345
8   libSystem.B.dylib               0x97d056a2 thread_start + 34

Thread 4:
0   libSystem.B.dylib               0x97cfd9d2 __workq_kernreturn + 10
1   libSystem.B.dylib               0x97cfdf68 _pthread_wqthread + 941
2   libSystem.B.dylib               0x97cfdb86 start_wqthread + 30

Thread 5:
0   libSystem.B.dylib               0x97cd80fa mach_msg_trap + 10
1   libSystem.B.dylib               0x97cd8867 mach_msg + 68
2   CoreFoundation                  0x02b3a436 __CFRunLoopServiceMachPort + 150
3   CoreFoundation                  0x02a97984 __CFRunLoopRun + 708
4   CoreFoundation                  0x02a97350 CFRunLoopRunSpecific + 208
5   CoreFoundation                  0x02a9a614 CFRunLoopRun + 84
6   Clicky                          0x0001fdb7 +[ASIHTTPRequest runRequests] + 167 (ASIHTTPRequest.m:4093)
7   Foundation                      0x0014576c -[NSThread main] + 81
8   Foundation                      0x001456f8 __NSThread__main__ + 1387
9   libSystem.B.dylib               0x97d0581d _pthread_start + 345
10  libSystem.B.dylib               0x97d056a2 thread_start + 34

Thread 6:
0   libSystem.B.dylib               0x97cd80fa mach_msg_trap + 10
1   libSystem.B.dylib               0x97cd8867 mach_msg + 68
2   CoreFoundation                  0x02b3a436 __CFRunLoopServiceMachPort + 150
3   CoreFoundation                  0x02a97984 __CFRunLoopRun + 708
4   CoreFoundation                  0x02a97350 CFRunLoopRunSpecific + 208
5   CoreFoundation                  0x02a97271 CFRunLoopRunInMode + 97
6   Foundation                      0x0017ab86 +[NSURLConnection(NSURLConnectionReallyInternal) _resourceLoadLoop:] + 398
7   Foundation                      0x0014576c -[NSThread main] + 81
8   Foundation                      0x001456f8 __NSThread__main__ + 1387
9   libSystem.B.dylib               0x97d0581d _pthread_start + 345
10  libSystem.B.dylib               0x97d056a2 thread_start + 34

Thread 7:
0   libSystem.B.dylib               0x97cf7086 select$DARWIN_EXTSN + 10
1   CoreFoundation                  0x02acbb5e __CFSocketManager + 798
2   libSystem.B.dylib               0x97d0581d _pthread_start + 345
3   libSystem.B.dylib               0x97d056a2 thread_start + 34

Thread 8:
0   libSystem.B.dylib               0x97cfd9d2 __workq_kernreturn + 10
1   libSystem.B.dylib               0x97cfdf68 _pthread_wqthread + 941
2   libSystem.B.dylib               0x97cfdb86 start_wqthread + 30

Thread 0 crashed with X86 Thread State (32-bit):
  eax: 0x06641500  ebx: 0x000143f3  ecx: 0x0008e1c8  edx: 0x06606075
  edi: 0xb0000000  esi: 0x066554c4  ebp: 0xbfffdef8  esp: 0xbfffdec4
   ss: 0x0000001f  efl: 0x00010206  eip: 0x02cb5907   cs: 0x00000017
   ds: 0x0000001f   es: 0x0000001f   fs: 0x00000000   gs: 0x00000037
  cr2: 0xb0000000

4 个答案:

答案 0 :(得分:4)

您没有在dealloc ...

中释放您的操作队列

一个嫌疑人是代表团模式:

[request setDelegate:self];

如果self对象被销毁,而请求不被破坏,当请求'完成'时,它将尝试通知内存中的一些垃圾,从而崩溃。

更新:要修补此功能,请在取消之前添加此代码:

for (ASIHTTPRequest *request in queue.operations) 
{ 
    [request setDelegate: nil]; 
    [request setDidFinishSelector: nil];
}

答案 1 :(得分:4)

我认为jv42对于原因是正确的。但是,有一个方便的帮助清理代表......

-(void)dealloc {
    for (ASIHTTPRequest *request in queue.operations) { 
     [request clearDelegatesAndCancel]; 
    }
    [queue release];
    [super dealloc];
}

是否有人为此找到了更快的方法......也许是一个不涉及循环请求的方法?

答案 2 :(得分:0)

确保您正在运行最近的ASIHTTPRequest的git版本 - v1.7包含一些竞争条件,这些条件会在取消请求时导致崩溃。

答案 3 :(得分:0)

在运行带有多个请求的ASINetworkQueue时,我遇到了同样的情况。

我删除了队列的dealloc版本和自动释放。然后,我应用Leah的优秀建议来循环以取代代表。然后我将队列的发布放在queueRequestFinished委托中,它解决了我的问题!

bulkQueue = [[ASINetworkQueue alloc] init];

[bulkQueue setQueueDidFinishSelector:@selector(queueRequestFinished:)];

-(void)queueRequestFinished:(ASINetworkQueue *)queue
{
    for (ASIHTTPRequest *request in queue.operations) 
    { 
        [request setDelegate: nil]; 
        [request setDidFinishSelector: nil];
    }

}

希望这可以帮助别人! : - )