我遇到了一个场景,我有一个委托回调,可能发生在主线程或另一个线程上,我不知道哪个直到运行时(使用StoreKit.framework).
我还需要在该回调中更新UI代码,这需要在函数执行之前发生,因此我最初的想法是拥有这样的函数:
-(void) someDelegateCallback:(id) sender
{
dispatch_sync(dispatch_get_main_queue(), ^{
// ui update code here
});
// code here that depends upon the UI getting updated
}
Run Code Online (Sandbox Code Playgroud)
当它在后台线程上执行时,它工作得很好.但是,当在主线程上执行时,程序陷入僵局.
这本身似乎对我有意思,如果我读的文档dispatch_sync正确的,那么我希望它只是执行彻底,不担心它安排到runloop块,如说在这里:
作为优化,此函数在可能的情况下调用当前线程上的块.
但是,这不是太大的交易,它只是意味着更多的打字,这导致我采用这种方法:
-(void) someDelegateCallBack:(id) sender
{
dispatch_block_t onMain = ^{
// update UI code here
};
if (dispatch_get_current_queue() == dispatch_get_main_queue())
onMain();
else
dispatch_sync(dispatch_get_main_queue(), onMain);
}
Run Code Online (Sandbox Code Playgroud)
然而,这似乎有点倒退.这是制作GCD的一个错误,还是我在文档中遗漏了什么?
multithreading objective-c grand-central-dispatch objective-c-blocks
我在使用内置的Xcode单元测试框架SenTestingKit测试一些宏的中央调度代码时遇到了一些麻烦.我成功地解决了我的问题.我有一个单元测试,它构建一个块并尝试在主线程上执行它.但是,该块永远不会被实际执行,因此测试会挂起,因为它是同步调度.
- (void)testSample {
dispatch_sync(dispatch_get_main_queue(), ^(void) {
NSLog(@"on main thread!");
});
STFail(@"FAIL!");
}
Run Code Online (Sandbox Code Playgroud)
什么是导致它挂起的测试环境?
这段代码
dispatch_sync(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
NSLog(@"Main Thread? %d", [NSThread isMainThread]);
});
Run Code Online (Sandbox Code Playgroud)
表明我在主线程中.即使这样做:
queue = dispatch_queue_create("nonMainQueue", NULL);
Run Code Online (Sandbox Code Playgroud)
仍然报告说我在主队列中.这似乎是因为我正在使用dispatch sync.
这是否意味着我的代码与不使用dispatch_sync相同?另外:如果dispatch_sync什么都不做的话,那又有什么意义呢?
dispatch_queue_t queueA; // assume we have this
dispatch_sync(queueA, ^(){ // (a)
dispatch_sync(queueA, ^(){ // (b)
foo();
});
});
Run Code Online (Sandbox Code Playgroud)
一旦我们点击了第二个dispatch_sync,我们就会死锁:我们无法调度到queueA,因为有人(当前线程)已经在该队列上并且永远不会离开它.
只要我明白
dispatch_sync只需添加工作项(我避免使用"块",因为它可能会混淆)到queueA,然后这个工作项将被发送到queueA的目标队列,然后GCD将为此工作项保留一个线程
threadWorkItem我已经阅读了很多与此相关的线程,比如使用dispatch_sync进行死锁,为什么我们不能在当前队列中使用dispatch_sync?,为什么这个dispatch_sync()调用冻结?,...但是找不到好的解释.有人说dispatch_sync阻止队列,有人说它阻止当前线程,...... :(
那为什么会导致僵局呢?