Ios 某些设备上的“dispatch\u semaphore\u wait()”有问题吗?

Ios 某些设备上的“dispatch\u semaphore\u wait()”有问题吗?,ios,objective-c,macos,cocoa-touch,cocoa,Ios,Objective C,Macos,Cocoa Touch,Cocoa,我正在使用开源软件。 它为异步缓存节省了昂贵的数据。还有一种同步方法 它使用dispatch\u semaphore\u wait()等待操作结束 这在我的机器上很好用。在同事的机器上,它不会。 程序在dispatch\u semaphore\u wait()处停止工作。这对我来说绝对是不可复制的 上述方法在tableView:viewForTableColumn:row:,中调用 所以它是在主队列中执行的 知道为什么会这样吗?我必须在另一个队列中使用该方法吗?很可能您的线程已用完。需要在

我正在使用开源软件。 它为异步缓存节省了昂贵的数据。还有一种同步方法

它使用
dispatch\u semaphore\u wait()
等待操作结束



这在我的机器上很好用。在同事的机器上,它不会。 程序在
dispatch\u semaphore\u wait()
处停止工作。这对我来说绝对是不可复制的

上述方法在
tableView:viewForTableColumn:row:

中调用 所以它是在主队列中执行的


知道为什么会这样吗?我必须在另一个队列中使用该方法吗?

很可能您的线程已用完。需要在新线程中执行dispatch_semaphore_signal(信号量),它应该释放dispatch_semaphore_wait()(有关详细信息,请参阅objectForKey:block:)。如果操作系统无法分派新线程,那么您就卡住了,因为没有人会向您发送分派信号

发生的频率和时间取决于计算机/设备的速度、滚动表格的速度等。这就是为什么不能在计算机上重现此问题

这里的快速解决方案是通过使用相同的调度信号量方法,将timeout设置为dispatch_TIME_NOW,以保持较低的线程数,因为您可能不会阻塞主队列

不过,我更愿意改变TMCache.m的工作方式。我认为,在这种情况下,分派信号量的方法是不合理的——以牺牲可靠性为代价获得代码简洁性(将异步方法包装成同步方法)对我来说似乎不合适。我曾经用异步方法包装同步方法,但不是相反

这是解决办法


请注意,只修补了同步objectForKey方法。

很可能是线程不足。需要在新线程中执行dispatch_semaphore_signal(信号量),它应该释放dispatch_semaphore_wait()(有关详细信息,请参阅objectForKey:block:)。如果操作系统无法分派新线程,那么您就卡住了,因为没有人会向您发送分派信号

发生的频率和时间取决于计算机/设备的速度、滚动表格的速度等。这就是为什么不能在计算机上重现此问题

这里的快速解决方案是通过使用相同的调度信号量方法,将timeout设置为dispatch_TIME_NOW,以保持较低的线程数,因为您可能不会阻塞主队列

不过,我更愿意改变TMCache.m的工作方式。我认为,在这种情况下,分派信号量的方法是不合理的——以牺牲可靠性为代价获得代码简洁性(将异步方法包装成同步方法)对我来说似乎不合适。我曾经用异步方法包装同步方法,但不是相反

这是解决办法



请注意,只修补了同步objectForKey方法。

问题可能出在
objectForKey:block
上。你确定该块正在你同事的机器上执行吗?@Marcelofari我肯定不是,如果是,信号量将发出信号,队列将被解锁。但是为什么它没有被执行…也许
键是
nil
?@marcelofari如果
键是
nil
dispatch\u semaphore\u wait()
一开始就不会被调用…@marcelofari不是你的错,为了清晰起见,我应该发布整个方法。可能问题出在
objectForKey:block
上。你确定该块正在你同事的机器上执行吗?@Marcelofari我肯定不是,如果是,信号量将发出信号,队列将被解锁。但是为什么它没有被执行…也许
键是
nil
?@marcelofari如果
键是
nil
dispatch\u semaphore\u wait()!在我的机器上,它工作得很好,让我看看它是否对我的同事有效。我已经推出了一些新的提交来重构异步objectForKey:block:-所有3个都在一个调度线程中包装对同步对等方的调用。此外,还可以通过删除不必要的调用和延迟对象实例化来加快优化速度。现在在我的应用程序中效果很好-我有一个巨大的照片网格,里面装满了从远程服务器下载的照片。它现在滚动非常平稳,没有死锁。分析器显示约20个活动线程,低于约60个。谢谢!我仍在等待反馈。亲爱的Alex,很抱歉打扰你,但作为一名信号量专家,你可能知道这个谜题的答案!:)干杯谢谢你,亚历克斯!在我的机器上,它工作得很好,让我看看它是否对我的同事有效。我已经推出了一些新的提交来重构异步objectForKey:block:-所有3个都在一个调度线程中包装对同步对等方的调用。此外,还可以通过删除不必要的调用和延迟对象实例化来加快优化速度。现在在我的应用程序中效果很好-我有一个巨大的照片网格,里面装满了从远程服务器下载的照片。它现在滚动非常平稳,没有死锁。分析器显示约20个活动线程,低于约60个。谢谢!我仍在等待反馈。亲爱的Alex,很抱歉打扰你,但作为一名信号量专家,你可能知道这个谜题的答案!:)干杯
- (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;
}