![](/img/trans.png)
[英]Can you use cancel/isCancelled with GCD/dispatch_async?
[英]For loops with dispatch_async / GCD crash
所以我试图了解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次迭代后被取消分配。 我不确定该如何解决。 谢谢!
崩溃是由__block
说明符引起的。 通常,在该块的生存期内,将保留该块所使用的来自周围范围的每个对象变量。 这对于dispatch_async
或dispatch_after
尤其有用,并且意味着只要块未完成,对象就将有效。 这是一眼看不到的真正力量。 但是,当您要更改对象指针或原始变量值时,需要使用__block
说明符。 该说明符以不同的方式对待对象变量,并且不按块保留它们,因此允许在块完成之前将其释放。 这正是您正在发生的事情。 排队:
output = [NSFileHandle fileHandleForUpdatingAtPath:tempPath];
您正在创建将在不久的将来发布的自动发布对象。 由于您使用的是dispatch_async
这可能会在块仍在运行时发生,从而导致崩溃。
有两种解决方案:
您可以将本地变量设为类的实例变量,以延长该对象的寿命,
但是最简单的方法是删除__block
因为您无需在块内更改对象的指针,并且根本不需要此说明符。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.