параллельный фон загружает на iPhone

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

У меня есть функция addDonwload, который добавляет URL к списку URL для загрузки и проверяет, существует ли доступный слот бесплатной загрузки. Если существует тот, он сразу запускает загрузку. Когда один из концов загрузок, я выбираю первый список формы URL и запускаю новую загрузку.

Я использую NSURLConnection для загрузки, вот некоторый код

- (bool) TryDownload:(downloadInfo*)info
{
    int index;
    @synchronized(_asyncConnection)
    {
        index = [_asyncConnection indexOfObject:nullObject];
        if(index != NSNotFound)
        {
            NSLog(@"downloading %@ at index %i", info.url, index);
            activeInfo[index] = info;
            NSURLRequest *request = [NSURLRequest requestWithURL:info.url cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:15];

            [_asyncConnection replaceObjectAtIndex:index withObject:[[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately:TRUE]];
            //[[_asyncConnection objectAtIndex:i] scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];           

            return true;
        }
    }

    return false;
}

- (void)connectionDidFinishLoading:(NSURLConnection*)connection
{
  [self performSelectorOnMainThread:@selector(DownloadFinished:) withObject:connection waitUntilDone:false];
}

- (void)DownloadFinished:(id)connection
{
    NSInteger index = NSNotFound;
    @synchronized(_asyncConnection)
    {
        index = [_asyncConnection indexOfObject:(NSURLConnection*)connection];
    }

    [(id)activeInfo[index].delegate performSelectorInBackground:@selector(backgroundDownloadSucceededWithData:) withObject:_data[index]];
    [_data[index] release];
    [activeInfo[index].delegate release];
    @synchronized(_asyncConnection)
    {
        [[_asyncConnection objectAtIndex:index] release];
        [_asyncConnection replaceObjectAtIndex:index withObject:nullObject];            
    }
    @synchronized(downloadQueue)
    {
        [downloadQueue removeObject:activeInfo[index]];
        [self NextDownload];
    }
}

- (void)NextDownload
{
    NSLog(@"files remaining: %i", downloadQueue.count);
    if(downloadQueue.count > 0)
    {
        if([self TryDownload:[downloadQueue objectAtIndex:0]])
        {
            [downloadQueue removeObjectAtIndex:0];
        }
    }
}

_asyncConnection является моим массивом слотов загрузки (NSURLConnections) downloadQueue, список URL для загрузки

То, что происходит, вначале все работает хорошо, но после немногих загрузок мои соединения начинают исчезать. Загрузите запускается, но connection:didReceiveResponse: никогда не называется. Существует одна вещь в выходной консоли, что я не понимаю меня, который мог бы помочь немного. Normaly там - что-то как 24.01.2010 21:44:17.504 appName [3057:207] перед моими сообщениями NSLog. Я предполагаю, что число в квадратных скобках является некоторым app:thread идентификатором? все работает хорошо, в то время как существует то же число, но через какое-то время, "NSLog ("загрузка % в индексе %i", info.url, индекс)"; сообщения начинают иметь отличающийся что второе число. И когда это происходит, я прекращаю получать любые обратные вызовы для этого urlconnection.

Это сводило меня с ума, поскольку у меня есть строгие крайние сроки, и я не могу найти проблему. У меня нет многого опыта с iPhone dev и многопоточными приложениями. Я пробовал разные подходы, таким образом, мой код довольно грязен, но я надеюсь, что Вы будете видеть то, что я пытаюсь сделать здесь :)

btw, любой из Вас знаешь о существующем классе/lib, который я мог использовать, который будет полезен также. Я хочу параллельные загрузки со способностью o, динамично добавляют новые файлы для загрузки (настолько инициализирующий загрузчик вначале со всеми URL не полезен для меня),

5
задан Lope 22 May 2013 в 12:28
поделиться

5 ответов

В современных C++ обычно следует избегать указателей. Основная цель для указателей в наше время вращается вокруг того, что указатели могут быть полиморфными, тогда как явные объекты не.

, Когда вам нужен полиморфизм в наше время, хотя лучше использовать умный класс указателя - такой как станд.:: shared_ptr (если ваш компилятор поддерживает C++ 0x расширения), станд.:: tr1:: shared_ptr (если ваш компилятор не поддерживает C++ 0x, но действительно поддерживает TR1), или повышение:: shared_ptr.

-121--4460301-

Обычно используются объекты.
Его легче съесть яблоко, чем яблоко на палочке (ОК 2 метровая палочка, потому что я люблю конфетные яблоки).

В этом случае просто сделать его вектором < gVector3 >

Если у вас был вектор < g3Vector * > это означает, что вы динамически распределяете новые объекты g3Vector (используя оператор new). Если это так, то вам нужно вызвать delete по этим указателям в какой-то момент и std:: Vector не предназначен для этого.

Но каждое правило является исключением.

Если g3Vector огромный объект, который стоит много, чтобы скопировать (трудно сказать прочитать вашу документацию), то это может быть более эффективным, чтобы сохранить в качестве указателя. Но в этом случае я бы использовал boost::ptr_vector, так как это автоматически управляет сроком службы объекта.

-121--4460304-

В этом коде имеется множество серьезных проблем с памятью и с синхронизацией потоков.

Вместо того, чтобы вдаваться в них все, я задам следующий вопрос: Вы делаете это на каком-то фоне? Почему? IIRC NSURLConnection уже загружает файлы в фоновом потоке и вызывает делегата в потоке, на котором был создан NSURLConnection (например, в идеале главный поток).

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

Дальнейшее предложение: Вместо того, чтобы пытаться поддерживать параллельное позиционирование в двух массивах (и некоторый эскизный код в приведенном выше отношении), создайте один массив и получите объект, который содержит как NSURLConnection, ТАК И объект, представляющий результат. После завершения соединения можно просто освободить экземпляр соединения var. И родительский объект (и, следовательно, данные), когда вы закончите с данными.

2
ответ дан 15 December 2019 в 06:26
поделиться

Этот фрагмент может быть источником ошибки, вы освобождаете объект, на который указывает указатель activeInfo[index].delegate сразу после вызова асинхронного метода на этот объект.

[(id)activeInfo[index].delegate performSelectorInBackground:@selector(backgroundDownloadSucceededWithData:) withObject:_data[index]];
[_data[index] release];
[activeInfo[index].delegate release];
0
ответ дан 15 December 2019 в 06:26
поделиться

Используете Подключение: DidFailwitherror: ? Может быть время ожидания, который предотвращает успешное завершение загрузки.

Старайтесь избавиться от @synchronized блоков и посмотрите, что происходит.

Строка внутри квадратных скобок, кажется, идентификатор потоков, как вы уже догадались. Так что, возможно, вы заблокированы в @synchronized . На самом деле, я не вижу причину для переключения нити - все проблемный код должен работать в основной ните ( PerfortSelectorOnmaintHaintHead ) ...

Во всяком случае, нет необходимости использовать оба @synchronized и ShareSelectoronMaintHaintHead .

Кстати, я не видел NSURLConnection * Connection = [[NSURLConnection Alloc] initWithRequest: Запрос делегата: Self]; линия. Где вы инициируете связь?

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

0
ответ дан 15 December 2019 в 06:26
поделиться

Рассмотрим, что оставьте очередь загрузки вместе с подсчетом активных подключений, выпрыгивающих элементов с верхней части очереди, когда загрузки загрузки и слот становится свободным. Затем вы можете отстрелить объекты NSURLConnection асинхронно и обрабатывать события на главной ните.

Если вы обнаружите, что ваш параллельный подход запрещает выполнять всю обработку на главной ните, рассмотрим, что объекты посредничества менеджера между основным потоком загрузки кода и NSURLConnection. Используя этот подход, вы могли бы создать свой менеджер и получить его, чтобы использовать NSURLConnection синхронно на фоновой резьбе. Затем этот менеджер полностью занимается загрузкой и передает результат назад к его основным делегатам потока с использованием PerfortSelectiononmaintHaintHead: withobject: call. Каждая загрузка - это просто случай создания нового объекта Manager, когда у вас свободный слот и настроив его.

0
ответ дан 15 December 2019 в 06:26
поделиться

После установки Android SDK создает для вас сертификат debug подписи в хранилище ключей с именем debug.keystore . Подключаемый модуль Eclipse использует этот сертификат для подписи каждой создаваемой сборки приложения.

К сожалению, сертификат отладки действителен только в течение 365 дней. Для создания нового файла необходимо удалить существующий файл debug.keystore . Его расположение зависит от платформы - его можно найти в разделе Настройки - Android - Сборка - Хранилище отладочных ключей по умолчанию .

-121--1745073-

Дополнительные предметы для добавления в список, без особого порядка:

  • Производительность - задержка, полоса пропускания, масштабирование или другие факторы, связанные с поставляемым продуктом
  • Поддержка - У вас уже есть журнал, но как насчет сантехники в других диагностических измерениях (Java-JMX, Windows-WMI/счетчики производительности или что-то пользовательское)
  • Гибкость - трудности при изменении архитектуры позже (обычно это одна из тех вещей, которые чрезмерно выполняются и вызывают больше проблем, чем необходимо, но обсуждение должно присутствовать при оценке дизайна)
  • Модель многопоточности/модель блокировки - Ясно ли, как данные будут защищены? Как будет обрабатываться конфликт ресурсов?
  • Требования к ресурсам - потребление памяти на различных уровнях использования. Соответствует ли он вашим ограничениям?
  • Обработка ошибок - Когда что-то в продукте выходит из строя, поддерживает ли архитектура чистую обработку и уведомление о проблемах?
  • Понятно - Слишком сложные архитектуры, как правило, забываются во время реализации. Если большинство команды, и в особенности руководители, не могут сохранить архитектуру, это философия и правила, в голове, архитектура не будет иметь значения.
  • Согласованность. Пытается ли он использовать все возможные образцы или сосредоточиться на регулярных, повторяющихся узорах. Не то чтобы выбор правильного образца для каждой проблемы не является хорошей вещью, но наличие большого количества узоров может повлиять на понятность и привести к ошибкам реализации. Архитектор должен стараться демонстрировать все, что он знает (или самую последнюю классную вещь) в каждом проекте.
  • Тестируемый - помогает ли проект тестированию (системе и интеграции). Может ли тестирование быть автоматизированным или вы будете полагаться на армию тестеров, чтобы постоянно повторять регрессионное тестирование, чтобы вы знали, что ваша команда не сломала продукт?
  • Действительно ли архитектура решает проблему, которую вы пытаетесь решить, и в рамках этой проблемы? Не создавайте скребок, когда будет достаточно дуплексного режима.
-121--4859578-

Я рекомендую вам взглянуть на это: http://allseeing-i.com/ASIHTTPRequest/

Это довольно сложный набор классов с либеральными условиями лицензирования (также бесплатными).

Это может обеспечить большую функциональность, которую вы хотите.

1
ответ дан 15 December 2019 в 06:26
поделиться
Другие вопросы по тегам:

Похожие вопросы: