如何防止调度组不崩溃?
How to prevent dispatch group to not crash?
我正在使用以下代码等待异步任务完成。它工作了几次并崩溃了。 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;
}
知道它为什么随机崩溃以及如何解决这个问题吗?基本上,我想要实现的是调用几个异步任务,等待它们全部完成,然后继续其余的。
参考:How to wait past dispatch_async before proceeding?
如果 this
是 nil
,则不能使用 ->
取消引用 ivar。因此,典型的解决方案是创建在闭包运行时无法释放的强引用,并且 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
,它不会崩溃,而只会 return 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);
}];
});
}
我正在使用以下代码等待异步任务完成。它工作了几次并崩溃了。 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;
}
知道它为什么随机崩溃以及如何解决这个问题吗?基本上,我想要实现的是调用几个异步任务,等待它们全部完成,然后继续其余的。
参考:How to wait past dispatch_async before proceeding?
如果 this
是 nil
,则不能使用 ->
取消引用 ivar。因此,典型的解决方案是创建在闭包运行时无法释放的强引用,并且 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
,它不会崩溃,而只会 returnnil
.
我必须承认这看起来仍然不对(例如,如果 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);
}];
});
}