solan solan - 7 months ago 25
Swift Question

lock and unlock dispatch_queue_t in async task

I want lock

LockQueue2
to complete process and when unlock
LockQueue2
show "number is :"
number
in
dispatch_after
.

I need this output :


number set value 1

number is 1

number set value 2

number is 2

number set value 3

number is 3


let LockQueue = dispatch_queue_create("LockQueue", nil)

func test(num :Int){
var number = 0
let LockQueue2 = dispatch_queue_create("LockQueue2", nil)

dispatch_async(LockQueue){
LockQueue2.lock()
// any process or waiting
sleep(2)
dispatch_sync(LockQueue2) {
number = num
print("number set value ", number)
LockQueue2.unlock()
}
}
dispatch_async(dispatch_get_global_queue(QOS_CLASS_BACKGROUND, 0)){
// any process or waiting
sleep(3)
dispatch_after(LockQueue2) {
print("number is :", number)//*** show number set in last dispatch ***
}
}
}

test(1)
test(2)
test(3)

Rob Rob
Answer

If you're dealing with simple synchronous tasks, like you are, you can just use a serial queue:

let serialQueue = dispatch_queue_create("com.domain.app.serialqueue", nil)

func simpleSerialQueue(num: Int) {
    var number = 0

    dispatch_async(serialQueue){
        sleep(2)
        number = num
        print("number set value: ", number)
    }

    dispatch_async(serialQueue) {
        print("number is:", number)//*** show number set in last dispatch ***
    }          
}

simpleSerialQueue(1)
simpleSerialQueue(2)
simpleSerialQueue(3)

Or if you had an asynchronous task for which you wanted to wait for it to finish, you could use a semaphore:

let serialQueue = dispatch_queue_create("com.domain.app.serialqueue", nil)

func semaphoreExample(num: Int) {
    var number = 0

    let semaphore = dispatch_semaphore_create(0)

    // this will fire in 2 seconds

    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, Int64(NSEC_PER_SEC * 2)), serialQueue) {
        number = num
        print("number set value: ", number)
        dispatch_semaphore_signal(semaphore);
    }

    // this will start immediately, but will wait until the above semaphore is signaled

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) {
        print("going to wait for semaphore")
        dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER)
        print("number is:", number)
    }
}

semaphoreExample(1)

Frankly, semaphores would probably be my solution of last resort, as generally, other approaches handle this more elegantly. For example, I might use asynchronous NSOperation subclass when dealing with asynchronous processes: It requires a little more set up up-front, but handles asynchronous tasks really gracefully. See WWDC 2015 Advanced NSOperations for robust example.

Comments