我正在使用开源软件TMCache。它为异步缓存节省了昂贵的数据。还有一个同步方法。
它使用dispatch_semaphore_wait()来等待操作结束。
https://github.com/tumblr/TMCache/blob/master/TMCache/TMCache.m#l288
- (id)objectForKey:(NSString *)key
{
if (!key)
return nil;
__block id objectForKey = nil;
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
[self objectForKey:key block:^(TMCache *cache, NSString *key, id object) {
objectForKey = object;
dispatch_semaphore_signal(semaphore);
}];
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
#if !OS_OBJECT_USE_OBJC
dispatch_release(semaphore);
#endif
return objectForKey;
}这个在我的机器上运行得很好。但在同事的机器上却没有。该程序在dispatch_semaphore_wait()停止工作。对我来说这绝对是不可复制的。
上述方法在tableView:viewForTableColumn:row:中调用,
所以它在主队列中执行。
知道为什么会这样吗?必须在另一个队列中使用该方法吗?
发布于 2013-10-11 18:48:07
很可能你的线程用完了。应该释放dispatch_semaphore_signal()的dispatch_semaphore_wait()需要在一个新线程中执行(参见objectForKey:block:有关详细信息)。如果OS未能分派新线程,您就会陷入困境,因为没有人会向您发送dispatch_semaphore_signal。
它发生的频率和时间取决于计算机/设备的速度,你滚动表格的速度等等。这就是为什么你不能在你的电脑上复制这个问题。
这里的快速解决方案是通过使用相同的调度信号量方法(将超时设置为DISPATCH_TIME_NOW )来保持线程数低,因为您可能不会阻塞主队列。
不过,我更喜欢改变TMCache.m的工作方式。我认为,在这种情况下,调度信号量方法是不合理的--以牺牲可靠性为代价获得代码简洁(将异步方法包装为同步对应)对我来说似乎是不对的。我曾经用异步方法包装同步方法,但反之亦然。
这是解决办法
https://github.com/rushproject/TMCache
请注意,只修补了同步objectForKey方法。
https://stackoverflow.com/questions/19306934
复制相似问题