我正在使用以下代码来等待异步任务完成。它可以工作几次并崩溃。 updateFromTable
总是调用callback()
,以便使组呼叫保持平衡,但仍会崩溃。
- (void)updateFromTable:(Table *)table env:(Env *)env callback:(void (^)(void))callback {
[someasync usingBlock:^{
callback()
}];
}
- (NSString * _Nullable)process {
JSL * __weak weakSelf = self;
NSString __block *ret = nil;
dispatch_group_enter(_dispatchGroup);
dispatch_async(_repQueue, ^{
JSL *this = weakSelf;
[this updateFromTable:[this->_env table] env:this->_env callback:^{
ret = [some op .. ];
dispatch_group_leave(this->_dispatchGroup);
}];
});
dispatch_group_wait(_dispatchGroup, dispatch_time(DISPATCH_TIME_NOW, NSEC_PER_SEC));
info(@"%@", @"done");
return ret;
}
有人知道为什么它会随机崩溃吗?如何解决这个问题?基本上,我想要实现的是调用几个异步任务,等待所有异步任务完成,然后再进行其余的工作。
答案 0 :(得分:1)
如果->
为this
,则无法使用nil
取消引用ivars。因此,典型的解决方案是创建在闭包运行时无法释放的强引用,如果是return
,则创建nil
:
- (NSString * _Nullable)process {
typeof(self) __weak weakSelf = self;
[self asynchronousMethodWithCompletion:^{
typeof(self) strongSelf = weakSelf;
if (!strongSelf) { return; }
// can now safely use `strongSelf` here
});
...
}
这是“ weakSelf
-strongSelf
舞蹈”。您可以在需要确保self
不是nil
的情况下使用它,例如取消引用ivars(strongSelf->ivar
)。
因此:
- (NSString * _Nullable)process {
typeof(self) __weak weakSelf = self;
NSString __block *ret = nil;
dispatch_group_t group = dispatch_group_create();
dispatch_group_enter(group);
dispatch_async(_repQueue, ^{
typeof(self) strongSelf = weakSelf;
if (!strongSelf) { return; }
[strongSelf updateFromTable:[strongSelf->_env table] env:strongSelf->_env callback:^{
ret = [some op .. ];
dispatch_group_leave(group);
}];
});
dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
info(@"%@", @"done");
return ret;
}
其他一些观察结果:
调度组应该是方法的局部变量,而不是ivar。您的代码中无需引用此group
。
确保您的dispatch_group_leave
调用不超过dispatch_group_enter
调用的数量(即,不会多次调用此完成处理程序块)。
我建议您等待DISPATCH_TIME_FOREVER
(假设您希望它真的等待它完成)。
此外,如果这些是属性(我猜它们是在下划线的基础上),那么使用self.env
而不是self->_env
会更安全,因为它不会如果self
是nil
会崩溃,而只会返回nil
。
我必须承认这仍然看起来不正确(例如,如果updateFromTable
已经是异步的,为什么要麻烦地将其异步分配给_repQueue
;如果它是同步的,那么再次,为什么要异步地分配它只等它)。但是,如果没有看到updateFromTable
的实现,就无法进一步发表评论。
或者更好的是,使该方法异步:
- (void)processWithCompletion:(void (^)(NSString *))callback {
typeof(self) __weak weakSelf = self;
dispatch_async(_repQueue, ^{
typeof(self) strongSelf = weakSelf;
if (!strongSelf) { return; }
[strongSelf updateFromTable:[strongSelf->_env table] env:strongSelf->_env callback:^{
NSString *ret = [some op .. ];
callback(ret);
}];
});
}