I have a function which adds an observer on main thread, the callback of the observer is running in another thread, if the callback result is YES
, I continue do another task on main thread, otherwise I print error.
Here is the code, I use semaphore
to achieve it:
dispatch_queue_t semQueue;
-(void) myFunc {
/*MAIN THREAD*/
// I use GCD serial queue to signal semaphore, so that it can be thread safe
semQueue = dispatch_queue_create( "my.sem.queue", DISPATCH_QUEUE_SERIAL);
// create a semaphore
__block dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
// add observer with callback
[self addObserver:myObserver withCallback:^(BOOL result){
/* CODE HERE IS RUNNING IN ANOTHER THREAD*/
// if result is YES, I signal the semaphore to continue doing another task
if (result){
dispatch_sync(resultQueue,^{
// signal semaphore
dispatch_semaphore_signal(semaphore);
// log
NSLog("semaphore signaled");
});
}
}];
/*MAIN THREAD*/
// semaphore waits for the signal, timeout is 20seconds
dispatch_time_t timeOut = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(20 * NSEC_PER_SEC));
long waitResult = dispatch_semaphore_wait(semaphore, timeOut);
// if successful do other task, otherwise, print error
if (waitResult == 0) {
[self doAnotherTask];
} else {
print("Failed");
}
}
So, to recap, what I want to achieve with this function is to wait for the result from a callback of my observer, if it is successful, I continue do another task, otherwise print error. (callback is running in another thread.)
As you see in code, I use GCD to signal semaphore to make it thread safe.
When I run my function multiple times consecutively like this:
// run myFunc
[service myFunc];
[self doSimpleTaskInMainThread];
// run myFunc
[service myFunc];
[self doSimpleTaskInMainThread];
// run myFunc
[service myFunc];
...
When calling myFunc
for the 1st & 2nd time are working fine, after that the other calls sometimes hanging in the place after semaphore
is signaled. I see the log "semaphore signaled"
, then code is hanging for 20 seconds timeout, and then, it goes to main thread checks the result is YES
, and it starts to do another task.
My Questions:
- Why it is hanging even though semaphore is signaled ?
- Is there another way other than using semaphore to achieve this?
- Is it fine to use GCD to update that boolean flag
resultSucceed
? Other better options?
Aucun commentaire:
Enregistrer un commentaire