I want to wrap an async API that look like this:
[someObject completeTaskWithCompletionHandler:^(NSString *result) {
}];
into a synchronous method that I can call like this:
NSString *result = [someObject completeTaskSynchronously];
How do I do this? I did some doc reading and internet search, and attempt to use "dispatch_semaphore" to do try to achieve it like so:
-(NSString *) completeTaskSynchronously {
__block NSString *returnResult;
self.semaphore = dispatch_semaphore_create(0);
[self completeTaskWithCompletionHandler:^(NSString *result) {
resultResult = result;
dispatch_semaphore_signal(self.semaphore);
}];
dispatch_semaphore_wait(self.semaphore, DISPATCH_TIME_FOREVER);
return resultResult;
}
But this doesn't seem to work, it basically just halt at dispatch_semaphore_wait. Execution never reaches inside block that do the _signal. Anyone has code example on how to do this? I suspect that the block has to be on a different thread other the main thread? Also, assume I don't have access to the source code behind the async method.
In my discussion of “async over sync,” I strongly suggested that if you have an API which internally is implemented synchronously, you should not expose an asynchronous counterpart that simply wraps the synchronous method in Task. Run.
When a asynchronous method is executed, the code runs but nothing happens other than a compiler warning.
dispatch_semaphore_wait
blocks the main queue in your example. You can dispatch the async task to a different queue:
__block NSString *returnResult;
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0UL);
dispatch_async(queue,^{
result = [someObject completeTaskSynchronously];
});
Or use some other system, like NSRunLoop:
__block finished = NO;
[self completeTaskWithCompletionHandler:^(NSString *result) {
resultResult = result;
finished = YES;
}];
while (!finished) {
// wait 1 second for the task to finish (you are wasting time waiting here)
[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:1]];
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With