Reputation: 4825
I am working with a library (Fast Image Cache) that has a method that takes a block that it may or may not call synchronously.
I am trying to determine which is the case within the block using the following code:
__block BoolSleeve* sync = [[BoolSleeve alloc] init];
sync.value = YES;
[object block:^{
if (sync.value)
NSLog(@"sync");
else
NSLog(@"async");
}];
sync.value = NO;
However, so far this and many related variations have failed to print "async" when expected.
BTW, BoolSleeve is:
@interface BoolSleeve : NSObject
@property (assign, nonatomic) BOOL value;
@end
Upvotes: 0
Views: 242
Reputation: 9030
As was quoted from the documentation:
If the requested image already exists in the image cache, then the completion block is immediately called synchronously on the current thread. If the requested image does not already exist in the image cache, then the completion block will be called asynchronously on the main thread as soon as the requested image is available.
Given the above information, if you wish to determine if it will be run synchronously on the current thread, or asynchronously on the main thread, you will need to know only 1 thing:
Does the image currently exist in cache?
To find out, call the imageExistsForEntity:withFormatName:
method of your object. Doing so will let you know if it exists in cache. With that information, you will then be able to determine if it will run synchronously on the current thread, or asynchronously on the main thread.
The issue that you are having, I believe, is that you are attempting to make that determination after the block has been called. By this time, there is no way for you to know since the framework doesn't hand you any information regarding this. Instead, you will have to determine before your method call.
So, your code might look something like this:
...
BOOL isSynchronousOnCurrentThread = [object imageExistsForEntity...];
...
[object block:^{
if (isSynchronousOnCurrentThread)
NSLog(@"Is Synchronous on current thread");
else
NSLog(@"Is Asynchronous on main thread");
}];
But, be careful - the framework developer may later decide to change that. And since you will have married your code with a decision process only known to the framework, then your code could possibly break.
Note:
To determine which is the current thread, you can call [NSThread currentThread]
.
As an aside: I am curious why you would need to know that (for my own dark and sinister reasons). Perhaps there is a better way to do what you want, or maybe is indicative of a larger problem.
Upvotes: 2
Reputation: 8029
You should have control over how you call your blocks, it shouldn't be up to the block scope to decide what to do.
Dispatch asynchronous:
void
dispatch_async(dispatch_queue_t queue, void (^block)(void));
Dispatch synchronous:
void
dispatch_sync(dispatch_queue_t queue, void (^block)(void));
e.g.
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0), ^{
// background operation
});
dispatch_sync(dispatch_get_main_queue(), ^{
// synchronous operation
});
dispatch_async(dispatch_get_main_queue(), ^{
// runs the block in the next run-loop on the main thread
});
You can get more advanced by creating your own queues and managing what gets dispatched on them, see for more : https://developer.apple.com/library/mac/documentation/Darwin/Reference/Manpages/man3/dispatch_queue_create.3.html#//apple_ref/doc/man/3/dispatch_queue_create
Upvotes: -1
Reputation: 8200
Try this:
if ([NSThread isMainThread])
That will let you know if what you're running is executing on the main thread or not. If not, you can use the following before your block and in your block to get the current thread for each:
[NSThread currentThread]
Then you can compare the two to see if they're the same thread or not.
Upvotes: 1