【发布时间】:2012-03-16 11:03:04
【问题描述】:
我最近在调试一个操作的僵尸问题,发现在队列上调用cancelAllOperations并没有取消有问题的操作,实际上,即使操作仍在运行,操作队列也是空的。
该结构是一个视图控制器,它从网络上异步加载一组图像并对其进行一些更改。相关(匿名)摘录如下:
@implementation MyViewController
- (id) init
{
(...)
mOperationQueue = [[NSOperationQueue alloc] init];
(...)
}
- (void) viewDidAppear:(BOOL)animated
{
(...)
MyNSOperation * operation = [[MyNSOperation alloc] initWithDelegate:self andData:data];
[mOperationQueue addOperation:operation];
[operation release];
(...)
}
- (void) dealloc
{
(...)
[mOperationQueue cancelAllOperations];
[mOperationQueue release];
(...)
}
- (void) imagesLoaded:(NSArray *)images
{
(...)
}
以及有问题的操作:
@implementation MyNSOperation
- (id) initWithDelegate:(id)delegate andData:(NSDictionary *)data
{
self = [super init];
if (self)
{
mDelegate = delegate; // weak reference
mData = [data retain];
(...)
}
return self;
}
- (void) main
{
NSAutoReleasePool * pool = [[NSAutoReleasePool alloc] init];
mImages = [[NSMutableArray alloc] init];
// load and compose images
mAlteredImages = (...)
[self performSelectorOnMainThread:@selector(operationCompleted) withObject:nil waitUntilDone:YES];
[pool release];
}
- (void)operationCompleted
{
if (![self isCancelled])
{
[mDelegate imagesLoaded:mAlteredImages];
}
}
观察到的流程如下:
- 显示视图控制器,调用 init 和 viewDidAppear 开始操作。
- [mOperationQueue 操作] 只包含一个元素;
- 不久之后,操作进入 main 和
- 视图控制器在操作完成之前由用户退出。
- 在视图控制器上调用dealloc(因为操作保持弱引用)
- [mOperationQueue 操作] 包含零 (!) 个元素
- cancelAllOperations 被发送到操作队列
- [NSOperation cancel] 未被调用,导致应用可见的虚假状态。
- dealloc 完成
- 操作完成
- isCancelled 返回 false,导致僵尸调用
然而,NSOperationQueue 的文档明确指出“操作在完成任务之前一直处于排队状态。”这看起来像是违约。
我已通过保留对操作的引用并手动发送取消来修复崩溃,但我想知道为什么原始方法无法防止进一步的问题。有人可以对此有所了解吗?
提前致谢。
【问题讨论】:
-
@Combuster...你能在这里分享你的工作代码吗
标签: ios multithreading nsoperation nsoperationqueue