6

Al trabajar con algún código, me encuentro con ejecutar bucles, que soy nuevo, dentro de NSOperation s.Usando NSThread dormir en una NSOperation

Los NSOperation s están ocupados descargando datos, y mientras están ocupados, hay código para esperar a que se completen las descargas, en forma de NSRunLoop sy thread sleeping.

este código en particular es de interés para mí:

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

He leído sobre los bucles de estreno y runMode:beforeDate: esperará una fuente de entrada o un tiempo de espera. Aunque no soy 100%, lo que cuenta como fuente de entrada.

En la primera ejecución de esto siempre devuelve NO e ingresa al sleepForTimeInterval:. ¿Es esto malo?

En una clase de utilidad particular, está alcanzando el sleepForTimeInterval: mucho, una vez para cada hilo, lo que perjudica significativamente el rendimiento.

¿Alguna mejor solución para esto o consejo?

Respuesta

2

Dormir bloquea el hilo. Tal vez cambie su código para usar performSelector: withObject: afterDelay. De esa forma su hilo puede continuar ejecutándose.

... 
    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

Parece que es necesario utilizar un concurrente NSOperation. Aquí está la parte correspondiente en la documentación de Apple:

A diferencia de una operación no concurrente, que se ejecuta de forma sincrónica, una operación simultánea se ejecuta de forma asíncrona. En otras palabras, cuando llama al método de inicio de una operación simultánea, ese método podría devolver antes de que se complete la tarea correspondiente. Esto podría suceder porque el objeto de operación creó un nuevo hilo para ejecutar la tarea o porque la operación llamó a una función asíncrona. No importa si la operación está en curso cuando el control vuelve a la persona que llama, solo que podría estar en curso. (...) En una operación concurrente, su método de inicio es responsable de comenzando la operación de manera asincrónica. Si genera un hilo o llama a una función asíncrona, lo hace desde este método. Al iniciar la operación, el método de inicio también debe actualizar el estado de ejecución de la operación según lo informado por el método isExecuting . Para ello, envíe notificaciones de KVO para la ruta de la clave 0Executing , que permite a los clientes interesados ​​saber que la operación se está ejecutando. Su método isExecuting también debe devolver el estado de una manera segura para subprocesos.

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

En otras palabras, se puede reemplazar el método -start en la subclase NSOperation, y tienen la propiedad de Ivar executing y finished. Este método iniciará la descarga en un hilo separado. Cuando se inicia la descarga, configura el indicador executing y activa KVO.Cuando finalice en este hilo, haga lo mismo con finished y executing. Parece complicado, pero en realidad es bastante simple.

Consulte también esta pregunta sobre Desbordamiento de pila con una gran explicación: Subclassing NSOperation to be concurrent and cancellable