dispatch_semaphore_wait不适用于并发后台NSOperation

时间:2016-12-12 13:35:10

标签: ios objective-c semaphore nsoperation

编辑:事实上,信号量与背景NSOperation完美配合,问题是有时操作会被取消,即使之前它有机会启动,这会产生对dispatch_semaphore_signal的额外调用并且允许传递两个dispatch_semaphore_wait而不停止线程。

我的iOS应用程序使用sqlite数据库作为数据存储(由于历史原因,没有CoreData)。当几个线程同时访问一个数据库连接时,sqlite崩溃,因此我可以使用dispatch_semaphore_wait,并在数据库打开时将信号量激活为dispatch_semaphore_create(1)。

我实现了一个数据库访问方法作为NSOperation(我需要取消功能)后,我的应用程序开始崩溃,我意识到即使数据库已经忙,dispatch_semaphore_wait也不会暂停线程。这通常发生在我从主线程执行快速数据库调用时,它与包含在NSOperation中的较大调用重叠。

以下是创建NSOperation的代码:

self.loadOperation = [NSBlockOperation blockOperationWithBlock:^{
    [database openDatabase];
    // read some data
}

self.loadOperation.queuePriority = NSOperationQueuePriorityLow;
self.loadOperation.qualityOfService = NSOperationQualityOfServiceUtility;
self.loadOperation.completionBlock = ^{
        [database closeDatabase];
};

NSOperationQueue* backgroundQueue = [[NSOperationQueue alloc] init];
[backgroundQueue addOperation:self.loadOperation];

以下是我如何管理对DB的访问:

- (instancetype)init
{
    if ( self = [super init] ) {
        databaseOpenSemaphore = dispatch_semaphore_create(1);
    }
    return self;
}

- (void)openDatabase
{
    dispatch_semaphore_wait(databaseOpenSemaphore, DISPATCH_TIME_FOREVER);  
    // open DB
}

- (void)closeDatabase
{       
    // close DB
    dispatch_semaphore_signal(databaseOpenSemaphore);
}

1 个答案:

答案 0 :(得分:0)

dispatch_semaphore_wait适用于并发后台NSOperation。

但是下次我应该考虑将优先级低的背景添加到队列后取消,但之前它有时间启动。在这种情况下,在我的实现中,此操作的completionBlock对dispatch_semaphore_signal进行了额外的调用,这会产生dispatch_semaphore_wait的“神秘”错误