Асинхронное NSURLConnection, параллельная NSOperation, когда использовать NSRunLoop?

#concurrency #ios4 #nsurlconnection #nsoperation #nsrunloop

#параллелизм #ios4 #nsurlconnection #nsoperation #nsrunloop

Вопрос:

Я пытаюсь запустить NSURLConnection async во вторичном потоке (целевой является iOS4), для этого я создал параллельную NSOperation, я думаю, что я почти у цели, но не совсем понимаю следующее:

1) в iOS4 NSOperationQueue addOperation запускает операцию в новом потоке из-за использования GCD, основываясь на технических вопросах и ответах QA1712, однако мои тесты (симулятор и iPad) показывают, что start () всегда вызывается в главном потоке, есть идеи, нужна ли мне проверка здесь: если в главном потоке, то создать новый?

2) если бы start действительно был вызван во вторичном потоке с помощью addOperation (), тогда я мог бы запустить свое асинхронное NSURLConnection, запланировав текущий NSRunLoop:

 [self.connection scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
[self.connection start];
  

как в примере LinkedImageFetcher здесь, и мне не нужно было бы выполнять цикл до завершения с:

 do {
    [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
} while (!isCompelted);
  

3) предполагая, что моя пользовательская функция NSOperation start () вызывается в основном потоке и 2) верна, и я создаю новый поток в start () для вызова моего пользовательского метода main () с:

 [NSThread detachNewThreadSelector:@selector(main) toTarget:self withObject:nil];
  

Затем в моем main () мне нужно запустить цикл выполнения текущего потока:

 do {
    [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
} while (!isCompelted);
  

Это единственный экземпляр, в котором мне удалось запустить NSURLConnection в параллельной NSOperation, но я не уверен, что мне действительно нужно запускать RunLoop, если поток был предоставлен GCD, как указано в технических примечаниях, могу ли я следовать логике в 2) или мне все равно придется запускать runloop потока? Как я могу протестировать поток, предоставляемый GCD?

Большое спасибо за любые разъяснения

Комментарии:

1. используйте простой метод подключения (как предложил @vaubry — Асинхронное NSURLConnection), а затем используйте NSOperationQueue для синтаксического анализа. Это поможет вам в достижении того, чего вы хотите.

Ответ №1:

Ну, я в конце концов разобрался с этим, поэтому подумал, что людям могут быть интересны детали:

1) start () был вызван в основном потоке, потому что я использовал [NSOperationQueue mainQueue] вместо создания новой очереди с помощью [[NSOperationQueue allc] init]. Однако проверка в NSOperation start() того, был ли текущий поток MainThread или нет, а затем вызов main () непосредственно оттуда или путем создания нового потока (в случае, если мы были в MainThread) не повредила.

2) Я понял, что LinkedImageFetcher слишком сложен для понимания циклов выполнения и потоков, и в этом нет необходимости, потому что тема не такая сложная. Все, что требуется в методе start(), — это поддерживать цикл выполнения вторичного потока до тех пор, пока мы не закончим (IsCompleted), все, что цикл выполнения для NSURLConnection выполняет прослушивание входных данных из соединения и запуск обратных вызовов (didreceivereponse, didreceivedata и т.д.).

3) да, запуск цикла выполнения необходим для получения обратных вызовов соединения в том же (вторичном в данном случае) потоке.

Для получения дополнительной информации смотрите Циклы выполнения в Руководстве по программированию потоков.

Комментарии:

1. Просто подумал, что я оставлю комментарий и скажу огромное спасибо! Я хотел реализовать несколько загрузок, используя NSOperation и NSOperationQueue, просто потому, что я могу отменить и ограничить количество одновременных загрузок вместо внедрения моего собственного менеджера очередей. Ваш вопрос и ваш ответ, в сотрудничестве с блогом Дейва Дрибина ( dribin.org/dave/blog/archives/2009/05/05/concurrent_operations ) помогло мне разобраться в концепции использования фоновых потоков с асинхронными вызовами. У меня все еще есть некоторые сомнения, но я задам их после повторного просмотра документов !:) Еще раз спасибо!

Ответ №2:

Я не уверен, что понимаю, чего вы пытаетесь достичь: API NSURLConnection имеет встроенный асинхронный метод initWithRequest:delegate:

Есть ли какая-то конкретная причина, по которой вы не можете это использовать?

Комментарии:

1. Более простой дизайн и масштабируемость, я бы тоже хотел проанализировать ответ в bg, и мне нужно выполнить более одного запроса одновременно. Спасибо

2. Использование NSOperationQueue позволяет добавлять экземпляры NSOperation, которые загружают данные. В очереди вы можете установить максимальное количество операций для одновременного выполнения. Вы можете счесть 2 или 4 оптимальными для производительности. С GCD вам пришлось бы управлять максимумом самостоятельно, плюс NSOperation легко отменить.