6

这是我需要做的。我希望 dispatch_sync 是使用 GCD 的最佳方式

我有一段关键部分代码放在 Appdelegate 的 applicationDidBecomeActive 回调中。

我将该方法包装在 dispatch_sync 调用中,以便无论调用多少次 applicationDidBecomeActive 都只调用一次

- (void)applicationDidBecomeActive:(UIApplication *)application{    
dispatch_sync(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{    
    NSLog(@"Thread created");
    //crtical code
    [self runCriticalSection];        
});}

这是使用 dispatch_sync 的正确方法吗?

4

2 回答 2

15

dispatch_sync()直到块完成才返回,这意味着 applicationDidBecomeActive直到runCriticalSection完成执行才返回。

这可能不是您想要的,因此您必须使用dispatch_async()(如其他答案中所述)。

runCriticalSection但是如果前一个仍在运行,您不希望另一个启动。这可以通过“计数信号量”(也是 GCD 的一个特性)来实现:

static dispatch_semaphore_t sema; // The semaphore
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
    // Initialize with count=1 (this is executed only once):
    sema = dispatch_semaphore_create(1);
});

// Try to decrement the semaphore. This succeeds if the count is still 1
// (meaning that runCriticalSection is not executing), and fails if the 
// current count is 0 (meaning that runCriticalSection is executing):
if (dispatch_semaphore_wait(sema, DISPATCH_TIME_NOW) == 0) {
    // Success, semaphore count is now 0.
    // Start asynchronous operation.
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        //critical code
        [self runCriticalSection];
        // Increment the semaphore count (from 0 to 1), so that the next call
        // to applicationDidBecomeActive will start a new operation:
        dispatch_semaphore_signal(sema);
    });
}
于 2013-05-01T21:18:12.007 回答
0

runCriticalSection方法将被多次调用,只是不会同时调用,所以我不知道这是否是您想要实现的。

dispatch_sync只需将指定的块添加到串行队列(默认优先级全局队列)中,因此如果applicationDidBecomeActive连续两次被触发,则队列将包含两个将运行的块runCriticalSection。随着第一个开始并完成其执行,第二个将开始,因此不会同时执行两个块。

这是预期的行为吗?如果是这样,dispatch_sync是要走的路。

作为附加组件:如果runCriticalSection执行繁重的操作,请考虑dispatch_sync将阻塞运行该applicationDidBecomeActive方法的线程(如果您不从另一个线程手动调用该方法,则为主线程),直到该操作完成。

如果您想避免这种情况,您应该执行以下操作:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{    
    [self runCriticalSectionOnComplete:^{
       // If you want to perform something on completion, place it here. This is called asynchronously, without blocking the main thread.
    }];        
});

dispatch_async将块添加到队列后立即返回,同时dispatch_sync等待块内的代码完成。

于 2013-05-01T20:54:21.227 回答