我无法暂停gcd查询。以下是一些演示此问题的代码:
static dispatch_queue_t q=nil;
static void test(int a){
if(q){
dispatch_suspend(q);
dispatch_release(q);
q=nil;
}
q=dispatch_get_global_queue(0,0);
dispatch_async(q,^ {
while(1){NSLog(@"query %d",a);sleep(2);}
});
}
int main(int argc, const char* argv[]){
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
test(1);
//blah blah blah
test(2);
while(1){}
[pool release];
return 0;
}
我正在尝试做的是在第二次调用函数测试时暂停,释放和重新初始化查询q,但显然我的代码是错误的,并且查询q的两个实例都继续运行。
非常感谢您的帮助,谢谢。
答案 0 :(得分:41)
在实际调用dispatch_suspend()之前异步调度到队列的任何块都将在挂起生效之前运行。在您的代码中,您将异步触发一堆块,因此当您调用test(2)时,某些块可能仍在队列中,并且这些块将被执行。
如果您希望能够取消正在运行的作业,则需要按照自己的逻辑进行操作。 GCD故意不公开真正的取消API。你可以这样做:
@interface Canceller
{
BOOL _shouldCancel;
}
- (void)setShouldCancel:(BOOL)shouldCancel;
- (BOOL)shouldCancel;
@end
@implementation Canceller
- (void)setShouldCancel:(BOOL)shouldCancel {
_shouldCancel = shouldCancel;
}
- (BOOL)shouldCancel {
return _shouldCancel;
}
@end
static void test(int a){
static Canceller * canceller = nil;
if(q){
[canceller setShouldCancel:YES];
[canceller release];
dispatch_suspend(q);
dispatch_release(q);
q=nil;
}
canceller = [[Canceller alloc] init];
q=dispatch_get_global_queue(0,0);
dispatch_async(q,^ {
while(![canceller shouldCancel]){NSLog(@"query %d",a);sleep(2);}
});
}
通过这种方式,每个块将保持对一个对象的引用,该对象知道它是否应该停止工作。
答案 1 :(得分:5)
来自Apple GCD Reference:
dispatch_suspend
通过挂起调度对象,您的应用程序可以暂时阻止执行与该对象关联的任何块。 在完成通话时运行的任何阻止后发生暂停。调用此函数会增加对象的暂停计数,并调用dispatch_resume会减少它。当计数大于零时,对象保持挂起状态,因此您必须使用匹配的dispatch_resume调用平衡每个dispatch_suspend调用。
[大胆的雷]
我认为这是因为当执行一个块时,它会离开队列。所以,似乎你不能暂停已经执行的块。