Использование NSThread sleep в NSOperation - PullRequest
6 голосов
/ 19 января 2012

Работая с некоторым кодом, я сталкиваюсь с циклами выполнения, с которыми я новичок, внутри NSOperation s.

NSOperation s заняты загрузкой данных - и пока они занятыесть код для завершения загрузки в форме NSRunLoop s и спящего потока.

Этот код, в частности, представляет для меня интерес:

while (aCertainConditionIsTrue && [self isCancelled]==NO) {
     if(![[NSRunLoop currentRunLoop] runMode: NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:1.0]]){
        [NSThread sleepForTimeInterval:1.0];
     }
}

IВы прочитали о циклах выполнения, и runMode:beforeDate: будет ожидать источника ввода или тайм-аута.Хотя я не на 100% то, что считается входным источником.

При первом выполнении это всегда возвращает NO и достигает sleepForTimeInterval:.Это плохо?

В определенном служебном классе он сильно ударяется по sleepForTimeInterval: - по одному разу для каждого потока - что значительно снижает производительность.

Любые лучшие решения для этого или советы

Ответы [ 2 ]

2 голосов
/ 20 января 2012

Сон блокирует поток. Возможно, вы измените свой код на использование executeSelector: withObject: afterDelay. Таким образом, ваш поток может продолжать работать.

    ...
    done = NO;
    [self checkDoneCondition:nil];
    ...

- (void)checkDoneCondition:(id)object {
    if (aCertainConditionIsTrue && [self isCancelled]==NO) {
        if(...) {
            [self performSelector:@selector(checkDoneCondition:) withObject:[con error] afterDelay:1.0];
        } else {
            done = YES;
        }
    }
}
1 голос
/ 10 марта 2012

Похоже, вам нужно использовать одновременную операцию NSOperation.Вот соответствующая часть в документации Apple:

В отличие от непараллельной операции, которая выполняется синхронно, параллельная операция выполняется асинхронно.Другими словами, когда вы вызываете метод запуска параллельной операции, этот метод может вернуться до завершения соответствующей задачи.Это может произойти из-за того, что объект операции создал новый поток для выполнения задачи, или потому что операция вызвала асинхронную функцию.На самом деле не имеет значения, выполняется ли операция, когда управление возвращается к вызывающей стороне, только то, что она может быть продолжена.(...) В параллельной операции ваш метод запуска отвечает за запуск операции асинхронным способом.Независимо от того, порождаете ли вы поток или вызываете асинхронную функцию, вы делаете это из этого метода.После запуска операции ваш метод запуска должен также обновить состояние выполнения операции, как сообщается методом isExecuting.Вы делаете это, отправляя уведомления KVO на путь ключа isExecuting, который позволяет заинтересованным клиентам узнать, что операция сейчас выполняется.Ваш метод isExecuting также должен возвращать статус в поточно-ориентированном виде.

(из https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/NSOperation_class/Reference/Reference.html)

Другими словами, вы можете переопределить метод -start в вашей NSOperationподкласс, и иметь ivar для свойства executing и finished. Этот метод начнет загрузку в отдельном потоке. Когда загрузка начнется, вы устанавливаете флаг executing и запускаете KVO. Когда он заканчивается в этом потокевы делаете то же самое с finished и executing. Это кажется сложным, но на самом деле это довольно просто.

См. также этот вопрос о переполнении стека с хорошим объяснением: Подклассы NSOperation для одновременности исократимое

...