Buscar..


Sintaxis

  • Swift 3.0

  • DispatchQueue.main // Obtener la cola principal

  • DispatchQueue (etiqueta: "my-serial-queue", atributos: [.serial, .qosBackground]) // Crea tu propia cola serial privada

  • DispatchQueue.global (atributos: [.qosDefault]) // Accede a una de las colas simultáneas globales

  • DispatchQueue.main.async {...} // Distribuye una tarea de forma asíncrona al hilo principal

  • DispatchQueue.main.sync {...} // Distribuye una tarea de forma sincrónica al hilo principal

  • DispatchQueue.main.asyncAfter (fecha límite: .now () + 3) {...} // Distribuye una tarea de forma asíncrona al hilo principal que se ejecutará después de x segundos

  • Swift <3.0

  • dispatch_get_main_queue () // Obtenga la cola principal ejecutándose en el hilo principal

  • dispatch_get_global_queue (dispatch_queue_priority_t, 0) // Obtener cola global con prioridad especificada dispatch_queue_priority_t

  • dispatch_async (dispatch_queue_t) {() -> Void in ...} // Distribuye una tarea de forma asíncrona en la dispatch_queue_t especificada

  • dispatch_sync (dispatch_queue_t) {() -> Void in ...} // Distribuye una tarea de forma síncrona en el dispatch_queue_t especificado

  • dispatch_after (dispatch_time (DISPATCH_TIME_NOW, Int64 (nanosegundos)), dispatch_queue_t, {...}); // Enviar una tarea en la dispatch_queue_t especificada después de nanosegundos

Obtención de una cola de Grand Central Dispatch (GCD)

Grand Central Dispatch trabaja en el concepto de "Dispatch Queues". Una cola de envío ejecuta las tareas que usted designa en el orden en que se pasan. Hay tres tipos de colas de despacho:

  • Serial Dispatch Queues (colas de envío privado) se ejecutan una tarea a la vez, en orden. Se utilizan con frecuencia para sincronizar el acceso a un recurso.
  • Las colas de despacho simultáneas (también conocidas como colas de despacho globales) ejecutan una o más tareas simultáneamente.
  • La cola de envío principal ejecuta tareas en el hilo principal.

Para acceder a la cola principal:

3.0
let mainQueue = DispatchQueue.main
3.0
let mainQueue = dispatch_get_main_queue()

El sistema proporciona colas de despacho globales simultáneas (globales a su aplicación), con diferentes prioridades. Puede acceder a estas colas utilizando la clase DispatchQueue en Swift 3:

3.0
let globalConcurrentQueue = DispatchQueue.global(qos: .default)

equivalente a

let globalConcurrentQueue = DispatchQueue.global()
3.0
let globalConcurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)

En iOS 8 o posterior, los posibles valores de calidad de servicio que se pueden pasar son .userInteractive , .userInitiated , .default , .utility y .background . Estos reemplazan las constantes DISPATCH_QUEUE_PRIORITY_ .

También puede crear sus propias colas con diferentes prioridades:

3.0
let myConcurrentQueue = DispatchQueue(label: "my-concurrent-queue", qos: .userInitiated, attributes: [.concurrent], autoreleaseFrequency: .workItem, target: nil)
let mySerialQueue = DispatchQueue(label: "my-serial-queue", qos: .background, attributes: [], autoreleaseFrequency: .workItem, target: nil)
3.0
let myConcurrentQueue = dispatch_queue_create("my-concurrent-queue", DISPATCH_QUEUE_CONCURRENT)
let mySerialQueue = dispatch_queue_create("my-serial-queue", DISPATCH_QUEUE_SERIAL)

En Swift 3, las colas creadas con este inicializador son en serie de forma predeterminada, y pasar .workItem para la frecuencia de liberación automática garantiza que se crea y se vacía un grupo de autorelease para cada elemento de trabajo. También existe .never , lo que significa que usted mismo administrará sus propios grupos de autorelease, o .inherit que hereda la configuración del entorno. En la mayoría de los casos, es probable que no use .never excepto en casos de personalización extrema.

Ejecución de tareas en una cola de Grand Central Dispatch (GCD)

3.0

Para ejecutar tareas en una cola de envío, use los métodos sync , async y after .

Para enviar una tarea a una cola de forma asíncrona:

let queue = DispatchQueue(label: "myQueueName")

queue.async {
    //do something
    
    DispatchQueue.main.async {
        //this will be called in main thread
        //any UI updates should be placed here
    }
}
// ... code here will execute immediately, before the task finished

Para enviar una tarea a una cola de forma síncrona:

queue.sync {
    // Do some task
}
// ... code here will not execute until the task is finished

Para enviar una tarea a una cola después de un cierto número de segundos:

queue.asyncAfter(deadline: .now() + 3) {
    //this will be executed in a background-thread after 3 seconds
}
// ... code here will execute immediately, before the task finished

NOTA: ¡ Cualquier actualización de la interfaz de usuario debe llamarse en el hilo principal! Asegúrese de que coloca el código para las actualizaciones de la interfaz de usuario dentro de DispatchQueue.main.async { ... }

2.0

Tipos de cola:

let mainQueue = dispatch_get_main_queue()
let highQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0)
let backgroundQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0)

Para enviar una tarea a una cola de forma asíncrona:

dispatch_async(queue) {
    // Your code run run asynchronously. Code is queued and executed 
    // at some point in the future.
}
// Code after the async block will execute immediately

Para enviar una tarea a una cola de forma síncrona:

dispatch_sync(queue) {
    // Your sync code
}
// Code after the sync block will wait until the sync task finished

Para enviar una tarea después de un intervalo de tiempo (use NSEC_PER_SEC para convertir segundos a nanosegundos):

dispatch_after(dispatch_time(DISPATCH_TIME_NOW, Int64(2.5 * Double(NSEC_PER_SEC))), dispatch_get_main_queue()) {
    // Code to be performed in 2.5 seconds here
}

Para ejecutar una tarea de forma asíncrona y luego actualizar la interfaz de usuario:

dispatch_async(queue) {
    // Your time consuming code here
    dispatch_async(dispatch_get_main_queue()) {
        // Update the UI code 
    }
}

NOTA: ¡ Cualquier actualización de la interfaz de usuario debe llamarse en el hilo principal! Asegúrese de que coloca el código para las actualizaciones de la interfaz de usuario dentro de dispatch_async(dispatch_get_main_queue()) { ... }

Loops concurrentes

GCD proporciona un mecanismo para realizar un bucle, por lo que los bucles se producen simultáneamente entre sí. Esto es muy útil cuando se realizan una serie de cálculos computacionalmente costosos.

Considere este bucle:

for index in 0 ..< iterations {
    // Do something computationally expensive here
}

Puede realizar esos cálculos al mismo tiempo utilizando concurrentPerform (en Swift 3) o dispatch_apply (en Swift 2):

3.0
DispatchQueue.concurrentPerform(iterations: iterations) { index in
    // Do something computationally expensive here
}
3.0
dispatch_apply(iterations, queue) { index in
    // Do something computationally expensive here
}

El cierre del bucle se invocará para cada index de 0 a, pero sin incluir, iterations . Estas iteraciones se ejecutarán simultáneamente entre sí, y por lo tanto el orden en que se ejecutan no está garantizado. El número real de iteraciones que ocurren simultáneamente en un momento dado generalmente viene determinado por las capacidades del dispositivo en cuestión (por ejemplo, cuántos núcleos tiene el dispositivo).

Un par de consideraciones especiales:

  • concurrentPerform / dispatch_apply puede ejecutar los bucles simultáneamente entre sí, pero todo esto sucede de forma sincrónica con respecto al subproceso desde el que lo llama. Por lo tanto, no lo llames desde el hilo principal, ya que bloqueará ese hilo hasta que se complete el ciclo.

  • Debido a que estos bucles se producen simultáneamente entre sí, usted es responsable de garantizar la seguridad de los resultados. Por ejemplo, si actualiza algún diccionario con los resultados de estos cálculos computacionalmente costosos, asegúrese de sincronizar esas actualizaciones usted mismo.

  • Tenga en cuenta que hay algunos gastos generales asociados con la ejecución de bucles simultáneos. Por lo tanto, si los cálculos que se realizan dentro del bucle no son lo suficientemente intensivos en computación, puede encontrar que cualquier rendimiento obtenido mediante el uso de bucles concurrentes puede disminuir, si no compensarse completamente, por la sobrecarga asociada con la sincronización de todos estos subprocesos concurrentes.

    Por lo tanto, usted es responsable de determinar la cantidad correcta de trabajo a realizar en cada iteración del bucle. Si los cálculos son demasiado simples, puede emplear "zancada" para incluir más trabajo por bucle. Por ejemplo, en lugar de hacer un bucle concurrente con 1 millón de cálculos triviales, puede hacer 100 iteraciones en su bucle, haciendo 10.000 cálculos por bucle. De esa manera, se realiza suficiente trabajo en cada subproceso, por lo que la sobrecarga asociada con la administración de estos bucles simultáneos se vuelve menos significativa.

Ejecutar tareas en un OperationQueue

Puede pensar en un OperationQueue como una línea de tareas que esperan ser ejecutadas. A diferencia de las colas de despacho en GCD, las colas de operación no son FIFO (primero en entrar, primero en salir). En su lugar, ejecutan tareas tan pronto como están listas para ejecutarse, siempre que haya suficientes recursos del sistema para permitirlo.

Obtener el principal OperationQueue :

3.0
let mainQueue = OperationQueue.main

Crear un OperationQueue personalizado:

3.0
let queue = OperationQueue()
queue.name = "My Queue"
queue.qualityOfService = .default

La calidad del servicio especifica la importancia del trabajo o la cantidad de probabilidades de que el usuario cuente con los resultados inmediatos de la tarea.

Agregar una Operation a un OperationQueue :

3.0
// An instance of some Operation subclass
let operation = BlockOperation {
    // perform task here
}

queue.addOperation(operation)

Añadir un bloque a un OperationQueue :

3.0
myQueue.addOperation {
    // some task
}

Agregue múltiples Operation a un OperationQueue :

3.0
let operations = [Operation]()
// Fill array with Operations

myQueue.addOperation(operations)

Ajuste la cantidad de Operation se pueden ejecutar simultáneamente en la cola:

myQueue.maxConcurrentOperationCount = 3 // 3 operations may execute at once

// Sets number of concurrent operations based on current system conditions
myQueue.maxConcurrentOperationCount = NSOperationQueueDefaultMaxConcurrentOperationCount

La suspensión de una cola evitará que comience la ejecución de cualquier operación existente, no iniciada o de cualquier nueva operación agregada a la cola. La forma de reanudar esta cola es establecer isSuspended nuevo en false :

3.0
myQueue.isSuspended = true

// Re-enable execution
myQueue.isSuspended = false

La suspensión de un OperationQueue no detiene o cancela las operaciones que ya se están ejecutando. Uno solo debe intentar suspender una cola que usted creó, no las colas globales o la cola principal.

Creación de operaciones de alto nivel

Foundation Framework proporciona el tipo de Operation , que representa un objeto de alto nivel que encapsula una parte del trabajo que puede ejecutarse en una cola. La cola no solo coordina el rendimiento de esas operaciones, sino que también puede establecer dependencias entre operaciones, crear operaciones cancelables, restringir el grado de concurrencia empleado por la cola de operaciones, etc.

Operation están listas para ejecutarse cuando todas sus dependencias terminan de ejecutarse. La propiedad isReady cambia a true .

Cree una subclase de Operation no concurrente simple:

3.0
class MyOperation: Operation {

    init(<parameters>) {
        // Do any setup work here
    }

    override func main() {
        // Perform the task
    }

}
2.3
class MyOperation: NSOperation {

    init(<parameters>) {
        // Do any setup work here
    }

    override func main() {
        // Perform the task
    }

}

Agregue una operación a un OperationQueue :

1.0
myQueue.addOperation(operation)

Esto ejecutará la operación simultáneamente en la cola.

Gestionar dependencias en una Operation .

Las dependencias definen otras Operation que deben ejecutarse en una cola antes de que esa Operation se considere lista para ejecutarse.

1.0
operation2.addDependency(operation1)

operation2.removeDependency(operation1)

Ejecutar una Operation sin una cola:

1.0
   operation.start()

Las dependencias serán ignoradas. Si se trata de una operación simultánea, la tarea aún puede ejecutarse simultáneamente si las descargas de su método de start funcionan en colas en segundo plano.

Operaciones concurrentes.

Si la tarea que debe realizar una Operation es, en sí misma, asíncrona, (por ejemplo, una tarea de datos URLSession ), debe implementar la Operation como una operación concurrente. En este caso, su implementación isAsynchronous debería devolver true , generalmente tendría un método de start que realiza alguna configuración y luego llama a su método main que ejecuta la tarea.

Cuando se inicia la implementación de una Operation asíncrona, debe implementar isExecuting , isFinished y KVO. Entonces, cuando se inicia la ejecución, isExecuting propiedad cambia a true . Cuando una Operation finaliza su tarea, isExecuting se establece en false y isFinished se establece en true . Si la operación se cancela, se cancela tanto el isCancelled como el cambio isFinished en true . Todas estas propiedades son clave-valor observable.

Cancelar una Operation .

Llamar cancel simplemente cambia la propiedad isCancelled a true . Para responder a la cancelación desde su propia subclase de Operation , debe verificar el valor de isCancelled al menos periódicamente dentro de main y responder adecuadamente.

1.0
operation.cancel()


Modified text is an extract of the original Stack Overflow Documentation
Licenciado bajo CC BY-SA 3.0
No afiliado a Stack Overflow