2012-08-10 107 views
1

所以我想了解GCD。我只是将数据追加一个长期运行的操作我下载这样的后:for dispatch_async/GCD崩溃循环

 NSFileManager *fileManager = [NSFileManager defaultManager]; 
     __block NSFileHandle *output; 
     output = [NSFileHandle fileHandleForUpdatingAtPath:tempPath]; 
     __block NSError *error = nil; 
     BOOL success; 
     dispatch_queue_t stitchQueue = dispatch_queue_create("com.test", NULL); 

for (NSString *packetName in listOfFiles) { 
      dispatch_async(stitchQueue, { 
       NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 
       NSString *packetPath = [[self applicationDocumentsDirectory] stringByAppendingPathComponent:packetName]; 

      NSData *packetData = [[NSData alloc] initWithContentsOfFile:packetPath]; 

      [output seekToEndOfFile]; 
      [output writeData:packetData]; 

      [fileManager removeItemAtPath:packetPath error:&error]; 
      NSLog(@"Removed file after appending data success: %i Error: %@", success, [error localizedDescription]); 
      [self updateManifestColumn:@"IsParsed" withValue:YES forFile:packetName inTable:tableName]; 

      packetData = nil; 
      [packetData release]; 
      [pool release]; 
      }); 
     } 
     [output closeFile]; 

// dispatch_async(//做我的下一个长远的任务数据缝合在一起后)

此代码的工作,如果我删除了dispatch_async调用。难道我做错了什么?当我用dispatch_async运行它时,它会成功通过一次迭代,然后崩溃。它在NSFileHandle上访问不良时崩溃。它似乎在迭代1次后解除分配。我不知道我需要做什么来解决这个问题。谢谢!

+0

您是否尝试过用'dispatch_async'封装整个'for(..)'? – Johnnywho 2012-08-10 08:13:08

+0

@Johnnywho是的,这也不起作用。 – Crystal 2012-08-10 18:20:48

回答

1

崩溃是由__block说明符引起的。通常情况下,该块所使用的周边范围内的每个对象变量都会保留该块的使用期限。这对dispatch_asyncdispatch_after尤其有用,并且意味着只要块未完成,对象就会有效。这是看不见的块的真正力量。但是,如果要更改对象指针或原始变量值,则需要使用__block说明符。该说明符以不同的方式处理对象变量,并且不会按块保留它们,从而允许在块完成之前解除分配它们。这正是你正在发生的事情。符合要求:

output = [NSFileHandle fileHandleForUpdatingAtPath:tempPath]; 

您正在创建自动释放的对象,该对象将在不久的将来发布。由于您正在使用dispatch_async这可能发生在块仍在运行时发生崩溃。

这里有两种解决方案:

  • 你可以让你的局部变量类的实例变量,以扩展该对象的生命周期,

  • 但最简单的方法是删除__block因为你不改变块内的对象指针,你根本不需要这个指定符。