Согласно документу Apple в NSOperation, мы должны переопределить метод неконкурентных операций main
и метод для параллельных операций start
. Но почему?NSOperation, start vs main
ответ
Я бы предположил, что параллельный и неконкурентный не только флаг, но и очень существенная разница. Имея два разных метода, он абсолютно уверен, что вы не используете параллельную операцию, в которой вы должны использовать неконкурентную или наоборот.
Если вы ошиблись, ваш код абсолютно не работает из-за этого дизайна. Это то, что вы хотите, потому что вы сразу это исправите. Если бы был только один метод, то использование одновременных вместо неконкурентных приведет к очень тонким ошибкам, которые могут быть очень трудно найти. И не одновременное, а не одновременное приведет к проблемам производительности, которые вы также можете пропустить.
Во-первых, имейте в виду, что «параллельные» и «неконкурентные» имеют несколько специализированных значений в NSOperation
, которые имеют тенденцию путать людей (и используются синонимично с «асинхронным/синхронным»). «Параллельный» означает «операция будет управлять своим собственным параллелизмом и состоянием». «Non-concurrent» означает «операция ожидает чего-то другого, обычно очереди, для управления его параллелизмом и требует обработки по умолчанию».
start
выполняет все операции по умолчанию. Частью этого является то, что он устанавливает isExecuting
, а затем вызывает main
и когда возвращается main
, он очищает isExecuting
и устанавливает isFinished
. Поскольку вы обрабатываете свое собственное состояние, вы не хотите этого (вы не хотите, чтобы завершить работу main
, чтобы завершить операцию). Поэтому вам нужно реализовать свой собственный start
и не звонить super
. Теперь вы все равно можете использовать метод main
, если хотите, но поскольку вы уже переопределяете start
(и это то, что звонки main
), большинство людей просто поместило весь код в start
.
Как правило, не используйте одновременные операции. Они редко то, что вы имеете в виду. Они определенно не означают «вещи, которые бегут в фоновом режиме». Оба вида операций могут выполняться в фоновом режиме (и ни один не имеет для запуска в фоновом режиме). Вопрос в том, хотите ли вы поведение системы по умолчанию (неконкурентное), или хотите ли вы обрабатывать все самостоятельно (параллельно).
Если ваша идея справиться с этим сама по себе - это «поворот на NSThread
», вы почти наверняка ошибаетесь (если вы не делаете этого, чтобы взаимодействовать с библиотекой C/C++, которая требует его). Если он создает очередь, вы, вероятно, ошибаетесь (у NSOperation есть всевозможные функции, чтобы избежать этого). Если это почти что-то похожее на то, что «вручную обрабатывать дела в фоновом режиме», вы, вероятно, ошибаетесь. По умолчанию (неконкурентное) поведение почти наверняка лучше, чем то, что вы собираетесь делать.
Если параллельные операции могут быть полезны в тех случаях, когда API, который вы используете, уже обрабатывает параллелизм для вас. Неконкурентная операция заканчивается, когда возвращается main
. Так что, если ваша операция обертывает асинхронную вещь, например, NSURLConnection
? Один из способов справиться с этим - использовать группу отправки, а затем позвонить dispatch_wait
в конце вашего main
, чтобы он не возвращался, пока все не сделано. Ничего страшного. Я делаю это все время. Но он блокирует поток, который в противном случае не был бы заблокирован, что отвлекает некоторые ресурсы, и в некоторых сложных случаях угол может привести к тупиковой ситуации (действительно. Apple утверждает, что это возможно, и они видели это, но я никогда не был способный заставить его произойти даже по назначению).
Итак, еще один способ, которым вы могли бы это сделать, - определить себя как параллельную операцию и установить isFinished
вручную в своих методах делегата NSURLConnection
. Подобные ситуации случаются, если вы обертываете другие асинхронные интерфейсы, такие как Dispatch I/O, и одновременные операции могут быть более эффективными для этого.
(Теоретически параллельные операции также могут быть полезны, если вы хотите запустить операцию без использования очереди. Я могу представить некоторые очень запутанные случаи, когда это имеет смысл, но это растягивается, и если вы в этой лодке, я полагаю, вы знаете, что делаете.)
Но если у вас есть какие-либо вопросы, просто используйте по умолчанию неконтактное поведение. Вы почти всегда можете получить такое поведение, которое вам нужно, с небольшими хлопотами (особенно если вы используете группу отправки), а затем вам не нужно обертывать мозг вокруг несколько запутанного объяснения «одновременного» в документах.
Я думаю, что после того, как основные финиширует, он устанавливает «isFinished» true. Это может быть одной из причин. – Anshu
Этот ответ, кажется, предполагает, что «одновременный» означает «работает в фоновом режиме» или что-то подобное. Это не то, что «одновременное» означает в NSOperation. Одновременные и неконкурентные операции могут выполняться в фоновом режиме (и, таким образом, «тонкие ошибки» вы упоминаете из-за многопоточных нарушений). Если они запускаются без очереди, то они могут быть полностью синхронными. Если запустить с очередью (с 10.6), то оба будут выполняться в фоновом потоке. По умолчанию 'start' вызывает' main'. Параллельные операции должны переопределять 'start' (по умолчанию выполняется неконкурентное поведение). Это источник разницы. –