2013-11-26 4 views
0

здания на качестве earlier вопрос: У меня есть NSOperationQueue, который выглядит следующим образом:NSOperationQueue с синхронным NSURLConnection

NSBlockOperation *block1 = [NSBlockOperation blockOperationWithBlock:^{ 
     [someObject someSelector]; 
    }]; 

NSBlockOperation *block2= [NSBlockOperation blockOperationWithBlock:^{ 
    [someObject anotherSelector]; 
}]; 

[block2 addDependency:block1]; 
[queue addOperation:block1]; 
[queue addOperation:block2]; 

Теперь внутри someSelector у меня есть:

returnData = [requesterObj getDataWithURL:(NSString*)url]; 

где getDataWithURL содержит что-то вроде:

NSURL *requestUrl = [NSURL URLWithString:strUrl]; 

NSMutableURLRequest *request = [NSMutableURLRequest requestUrl cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:timeout]; 
NSError *requestError; 
NSURLResponse *urlResponse = nil; 
NSData *urlData = [NSURLConnection sendSynchronousRequest:request returningResponse:&urlResponse error:&requestError]; 

Теперь, когда я добавляю точки останова, кажется, что второй блок вызывается перед тем, как NSURLConnection с первого блока заканчивается. Предположительно, потому что вызов getDataWithURL, сам по себе является асинхронным. Каков наилучший способ убедиться, что первый блок не будет завершен до того, как этот запрос вернется. Должен ли я попытаться использовать NSInvocation для размещения данных внутри returnData?

+0

Это должен быть решен путем установки зависимостей правильно. В опубликованном коде вы ** начинаете ** выполнять операции блока без установки зависимостей! Итак, что вы имеете в виду с _Assume также, что я установил зависимости ...? Можете ли вы разместить соответствующий код, где вы их установили? – Leijonien

+0

Нет, зависимости заданы правильно. Проблема заключается в том, что 'NSBlockOperation' не знает, что запрос async еще не завершен - он предполагает, что все материалы будут завершены после завершения блока. –

ответ

0

Если это работает для вашей ситуации, я бы просто упростил ситуацию и сделаю следующее.

NSBlockOperation *block1 = [NSBlockOperation blockOperationWithBlock:^{ 
    [someObject someSelector]; 
    [someObject anotherSelector]; 
}]; 
[queue addOperation:block1]; 
1
NSBlockOperation *block1 = [NSBlockOperation blockOperationWithBlock:^{ 
    [someObject someSelector]; 
}]; 

Это создает 'стандартный' работу блока. Эта операция считается завершенной ([block1 isFinished] является истиной) после выполнения блока, даже если операция асинхронной сети не завершена с точки зрения пользователя.

Поскольку вы не хотите этого, вам нужно подкласс NSOperation и явно сказать, когда ваша операция завершается путем переопределения его start:

- (void)completeOperation { 

    self.finished = YES; 
    self.executing = NO; 
} 

- (void)start { 

    if ([self isCancelled]) { 
     [self completeOperation]; 
     return; 
    } 

    self.executing = YES; 
    [self main]; 
    // this is where operation is set to finished in NSOperation 
} 

- (void)main { 
    [someObject someSelectorWithCompletionBlock: ^() { 
     [self completeOperation]; 
     // retain cycle may exist unless completion block is destroyed afterwards 
    }]; 
} 
0

Когда вы первый отправил your other question, я догадался, вы, возможно, занимаются асинхронными сетевыми запросами, и если вы хотите выполнять операции с асинхронными сетевыми запросами, обычно решается, что обертывание такого сетевого запроса в подклассе NSOperationas I discussed in the answer to your other question (и как илья впоследствии также описано здесь).

Ваш вопрос здесь предполагает, что вы звоните sendSynchronousRequest. Если это все, что вы делали, то этот шаблон подкласса NSOperation не понадобится, и вы сможете использовать addDependency без инцидентов. Но, похоже, вы обнаружили, что getDataWithURL был сам, представляя, что sendSynchronousRequest в свою собственную очередь операций, эффективно делая его асинхронным. Вы правильно определили, что если вы избавитесь от этой избыточной логики очереди операций от getDataWithURL, тогда ваша проблема будет решена и не потребуется подклассификация NSOperation.

Но, я бы не поспешил уволить этот подклассовый шаблон NSOperation, потому что у sendSynchronousRequest есть некоторые ограничения, с которыми вы могли бы обременять себя. А именно, эти запросы не могут быть отменены. Аналогичным образом, вы не можете добиться прогресса по этим запросам, поскольку они находятся в стадии разработки, и не обрабатывать какие-либо дополнительные функции, такие как аутентификация ответа на запрос или тому подобное. Возможно, вам не нужны какие-либо из этих функций, но из-за этих ограничений многие из нас обычно уклоняются от sendSynchronousRequestsendAsynchronousRequest тоже).

Более длинный срок, вы можете столкнуться с сетевыми вызовами NSURLConnectionDataDelegate, которые устраняют эти ограничения.В этом случае этот шаблон подкласса NSOperation может снова стать полезным. Или, еще лучше, подумайте об использовании фреймворка, например, AFNetworking, который обеспечивает сетевое решение на базе NSOperation, но делает для вас эту работу.

1

Я лично предпочитаю grand central dispatch, так как он делает код довольно понятным. Этот код будет вызывать два селектор в последовательности (из другого потока), а затем вызвать doneSelector в главном потоке:

dispatch_async(dispatch_get_global_queue(0,0), ^{ 
    // These will be called in sequence on a background thread 
    [someObject someSelector]; 
    [someObject anotherSelector] 

    dispatch_async(dispatch_get_main_queue(), ^{ 
     // These will be called on the main thread after the above are done 
     [someObject doneSelector]; 
     NSLog(@"Finished operation"); 
    }); 
}); 
+0

Если автор прав, что * вызов getDataWithURL сам по себе является асинхронным *, этот пример GCD также будет выполнять '[someObject anotherSelector]', в то время как асинхронный запрос обрабатывается. Фактически, это точно **, где 'NSOperation' помогает! –

+0

'[NSURLConnection sendSynchronousRequest:]' не является асинхронным запросом. Этот метод должен блокировать поток. – stevel

+0

Да, но, основываясь на наблюдениях автора, я предполагаю, что происходит больше асинхронных действий (или эта фраза вводит в заблуждение). –

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