相关疑难解决方法(0)

为什么我们不能在当前队列上使用dispatch_sync?

我遇到了一个场景,我有一个委托回调,可能发生在主线程或另一个线程上,我不知道哪个直到运行时(使用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

58
推荐指数
4
解决办法
3万
查看次数

主队列上的dispatch_sync在单元测试中挂起

我在使用内置的Xcode单元测试框架SenTestingKit测试一些宏的中央调度代码时遇到了一些麻烦.我成功地解决了我的问题.我有一个单元测试,它构建一个块并尝试在主线程上执行它.但是,该块永远不会被实际执行,因此测试会挂起,因为它是同步调度.

- (void)testSample {

    dispatch_sync(dispatch_get_main_queue(), ^(void) {
        NSLog(@"on main thread!");
    });

    STFail(@"FAIL!");
}
Run Code Online (Sandbox Code Playgroud)

什么是导致它挂起的测试环境?

objective-c grand-central-dispatch sentestingkit

41
推荐指数
4
解决办法
2万
查看次数

`[NSThread isMainThread]`总是返回YES

这段代码

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什么都不做的话,那又有什么意义呢?

grand-central-dispatch ios

12
推荐指数
2
解决办法
4500
查看次数

dispatch_sync中的dispatch_sync导致死锁

我刚刚在objc.io上看到了这完全异步,但找不到好的解释

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,因为有人(当前线程)已经在该队列上并且永远不会离开它.

只要我明白

  1. dispatch_sync只需添加工作项(我避免使用"块",因为它可能会混淆)到queueA,然后这个工作项将被发送到queueA的目标队列,然后GCD将为此工作项保留一个线程 threadWorkItem
  2. 当我到达(b)时,我在线程threadWorkItem(假设threadWorkItem是这个线程的名称),所以我认为将另一个工作项排入队列是没有问题的.但有人说,此时,queueA被保留,queueA被阻止 - >导致死锁,这让我感到困惑

我已经阅读了很多与此相关的线程,比如使用dispatch_sync进行死锁,为什么我们不能在当前队列中使用dispatch_sync?,为什么这个dispatch_sync()调用冻结?,...但是找不到好的解释.有人说dispatch_sync阻止队列,有人说它阻止当前线程,...... :(

那为什么会导致僵局呢?

deadlock sync dispatch grand-central-dispatch ios

4
推荐指数
1
解决办法
2516
查看次数