我有一个如下创建的串行队列:
self.myQueue = dispatch_queue_create("com.myDomain.myQueue", DISPATCH_QUEUE_SERIAL);
我有一个sqlite3数据库来存储我的数据。我不是每次都提交这些数据,而是每次获得一个数据时,都将其存储在一个缓冲区中 - 在这种情况下,是一个较低级别的基于CPP的“矢量”。
我将块添加到我的私有队列中以写入缓冲区。我使用dispatch_async()来做到这一点。在预定义的时间间隔之后,我将数据从缓冲区提交给DB。
当数据库低于5MB时,事情按预期工作 - 每个数据都进入,每个数据写入缓冲区,在时间间隔到期后,数据从缓冲区提交给数据库。
当DB大小增加到大于5 MB(大约)时,队列上的块似乎要等到将数据提交到DB的时间间隔才会执行。完成此时间后,会将一条记录写入缓冲区。下一次,时间间隔到期,数据被提交给DB,并且只有一条记录被写入缓冲区 - 这次是一个不同的记录,它在序列中我希望记录进入。 看起来每个块只有在我写入DB之后才会执行,只有在每次定义的时间间隔内才会执行。
注意:我已经检查过这些执行的块,干净地执行 - 没有错误。
我无法理解数据库的大小与私有队列上的块的非执行(如果有这样的话)之间的链接。
私人队列的线程宽度是否与它有关?还是内存问题?我会说DB的大小,但似乎每个时间间隔块正确执行。另外,我会直接说DB大小,但我无法写入缓冲区本身。
任何让我指点的想法或者这是一个不受我操控的操作系统问题吗?
答案 0 :(得分:1)
你是如何设置的还不是很清楚:听起来你有一个使用串行队列保护并发访问的向量。然后听起来你也在同一个队列上进行定期数据库操作。由于它是一个串行队列,如果数据库操作开始花费的时间越来越长,其他操作将在数据库操作后面进行备份。我建议仅将队列用于vector
上的基本操作,并使用第二个队列来管理数据库操作。它可能看起来像这样:
using namespace std;
dispatch_queue_t vectorQueue = NULL;
dispatch_queue_t dbQueue = NULL;
dispatch_source_t timer = NULL;
vector<whatever>* dbRecords = NULL;
void init()
{
dbRecords = new vector<whatever>();
vectorQueue = dispatch_queue_create(NULL, DISPATCH_QUEUE_SERIAL);
dbQueue = dispatch_queue_create(NULL, DISPATCH_QUEUE_SERIAL);
timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dbQueue);
dispatch_source_set_timer(timer, DISPATCH_TIME_NOW, NSEC_PER_SEC * 60, NSEC_PER_SEC);
dispatch_source_set_event_handler(timer, ^{
__block vector<whatever>* toCommit = NULL;
dispatch_sync(vectorQueue, ^{
if (dbRecords->size())
{
toCommit = new vector<whatever>(*dbRecords);
dbRecords->clear();
}
});
if (toCommit)
{
// Commit the records using your db code...
delete toCommit;
}
});
dispatch_resume(timer);
}
void enqueueRecord(whatever record)
{
dispatch_async(vectorQueue, ^{
dbRecords->push_back(record);
});
}
这样,不会备份传入的记录块,等待数据库操作。在vectorQueue
上执行的唯一块是对共享向量的操作。在提交数据库的时候,将共享向量中的记录复制到私有副本中,清除共享向量,并将私有副本发送到dbQueue
以提交。