2016-07-23 2 views
6

Согласно документу Apple в NSOperation, мы должны переопределить метод неконкурентных операций main и метод для параллельных операций start. Но почему?NSOperation, start vs main

ответ

0

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

Если вы ошиблись, ваш код абсолютно не работает из-за этого дизайна. Это то, что вы хотите, потому что вы сразу это исправите. Если бы был только один метод, то использование одновременных вместо неконкурентных приведет к очень тонким ошибкам, которые могут быть очень трудно найти. И не одновременное, а не одновременное приведет к проблемам производительности, которые вы также можете пропустить.

+0

Я думаю, что после того, как основные финиширует, он устанавливает «isFinished» true. Это может быть одной из причин. – Anshu

+0

Этот ответ, кажется, предполагает, что «одновременный» означает «работает в фоновом режиме» или что-то подобное. Это не то, что «одновременное» означает в NSOperation. Одновременные и неконкурентные операции могут выполняться в фоновом режиме (и, таким образом, «тонкие ошибки» вы упоминаете из-за многопоточных нарушений). Если они запускаются без очереди, то они могут быть полностью синхронными. Если запустить с очередью (с 10.6), то оба будут выполняться в фоновом потоке. По умолчанию 'start' вызывает' main'. Параллельные операции должны переопределять 'start' (по умолчанию выполняется неконкурентное поведение). Это источник разницы. –

8

Во-первых, имейте в виду, что «параллельные» и «неконкурентные» имеют несколько специализированных значений в 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, и одновременные операции могут быть более эффективными для этого.

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

Но если у вас есть какие-либо вопросы, просто используйте по умолчанию неконтактное поведение. Вы почти всегда можете получить такое поведение, которое вам нужно, с небольшими хлопотами (особенно если вы используете группу отправки), а затем вам не нужно обертывать мозг вокруг несколько запутанного объяснения «одновременного» в документах.

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