2013-10-10 3 views
0

Я использую программное обеспечение с открытым исходным кодом TMCache. Он экономит дорогостоящие данные для кеширования асинхронно. Существует также синхронный метод.Проблема с `dispatch_semaphore_wait()` на некоторых устройствах?

Он использует dispatch_semaphore_wait(), чтобы подождать, пока операция не закончится.


Source

- (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:,
поэтому он выполняется в главной очереди.

Любая идея, почему это происходит? Должен ли я использовать этот метод в другой очереди?

+0

Возможно, проблема заключается в 'objectForKey: block'. Вы уверены, что блок выполняется на компьютере вашего коллеги? –

+0

@MarceloFabri Я уверен, что это не так, если бы это было так, семафор был бы сигнализирован, и очередь была бы разблокирована. Но почему это не выполнено ... – NSAddict

+0

Может быть, 'key'' 'nil'? –

ответ

5

Скорее всего, у вас заканчиваются нитки. Рассылка_semaphore_signal (семафор), которая должна освободить dispatch_semaphore_wait(), должна быть выполнена в новом потоке (подробности см. В разделе objectForKey: block:). Если ОС не отправит этот новый поток, вы застряли, так как никто не отправит вам сообщение dispatch_semaphore_signal.

Как часто и когда это происходит, зависит от скорости компьютера/устройства, скорости прокрутки таблицы и т. Д. Поэтому вы не можете воспроизвести эту проблему на своем компьютере.

Быстрое решение заключается в том, чтобы поддерживать низкое число потоков, используя один и тот же подход семафора отправки с тайм-аутом, установленным на DISPATCH_TIME_NOW, поскольку вы не можете блокировать основную очередь.

Я бы предпочел изменить способ работы TMCache.m. Я считаю, что подход семафоров отправки не оправдан в этом случае - получение краткости кода (обертывание асинхронного метода в синхронный аналог) за счет надежности не кажется мне правильным. Я использовал обходные синхронные методы с асинхронными, но не наоборот.

Вот исправление

https://github.com/rushproject/TMCache

Обратите внимание, что было исправлено только синхронные методы objectForKey.

+0

Спасибо, Алекс! На моей машине он работает отлично, позвольте мне посмотреть, работает ли это для моего коллеги. – NSAddict

+0

Я запустил несколько новых коммитов для рефакторинга async objectForKey: block: - all 3 завершает вызов синхронным копиям в отправленном потоке. Также оптимизируйте скорость, отключив ненужные вызовы и отложив объекты.Сейчас работает красиво в моем приложении - у меня есть огромная сетка фотографий, заполненная фотографиями, загружаемыми из удаленного сервера. Теперь он прокручивается очень плавно и не блокирует. Профилер показывает около 20 активных потоков, начиная с ~ 60. –

+0

Спасибо! Я все еще жду обратной связи. – NSAddict

Смежные вопросы