I just took some time in the evening to play around with GCD, especially with dispatch_semaphore_t
because I never used it. Never had the need to.
So I wrote the following as a test:
- (void)viewDidLoad
{
UIView *firstView = [[UIView alloc] initWithFrame:(CGRect){{0, 0}, self.view.frame.size.width/4, self.view.frame.size.width/5}];
firstView.backgroundColor = [UIColor purpleColor];
[self.view addSubview:firstView];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^
{
for (long i = 0; i < 1000; i++)
{
sleep(5);
dispatch_async(dispatch_get_main_queue(), ^
{
firstView.layer.opacity = ((i%2) ? 0: 1);
});
}
});
dispatch_queue_t queue1 = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_group_t group1 = dispatch_group_create();
dispatch_group_async(group1, queue1, ^
{
sleep(3);
NSLog(@"dispatch group 1");
});
dispatch_group_notify(group1, queue1, ^
{
NSLog(@"dispatch notify 1");
});
dispatch_async(myQueue, ^
{
for(int z = 0; z < 10; z++)
{
NSLog(@"%i", z);
sleep(1);
}
dispatch_semaphore_signal(mySemaphore);
});
dispatch_semaphore_wait(mySemaphore, DISPATCH_TIME_FOREVER);
NSLog(@"Loop is Done");
}
If I ran the above, the output would be:
0
1
2
dispatch group 1
dispatch notify 1
3
4
5
6
7
8
9
Loop is Done
After the above, firstView
appears on the screen (before semaphore
the whole screen was black) and finally this gets executed:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^
{
for (long i = 0; i < 1000; i++)
{
sleep(5);
dispatch_async(dispatch_get_main_queue(), ^
{
firstView.layer.opacity = ((i%2) ? 0: 1);
});
}
});
Which only alternates the opacity
as the loop runs after semaphore
is done.
1.)
So, it seems that I have to wait until dispatch_semaphore
finish to do its work before any UI thing takes place.
BUT:
It seems like dispatch_group_t
runs concurrently with dispatch_semaphore
as shown from the output above (i.e., 1, 2, 3, ....).
???
2.)
And if I change the for loop
in the above to using: dispatch_async(dispatch_get_main_queue(), ^
instead of:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^
,
nothing gets shown on the screen even after semaphore
is done.
How so???
3.)
Furthermore if I change semaphore
to the following as opposed to using a global queue like in the above:
dispatch_async(dispatch_get_main_queue(), ^
{
for(int z = 0; z < 10; z++)
{
NSLog(@"%i", z);
sleep(1);
}
dispatch_semaphore_signal(mySemaphore);
});
Only dispatch_group
takes place; nothing else take places / get executed, not the for loop
in the above, including UI. Nothing.
4.)
So besides what I pointed out in the above, what can I do, in order to make semaphore
not blocking my UI and my other process and just let my UI and the other processes do their thing?
And as mentioned above, why changing the type of queue for semaphore
from global to main would cause nothing to be shown on screen and even the loop would not execute except dispatch_group
?
5.)
If I change semaphore
to:
dispatch_semaphore_t mySemaphore = dispatch_semaphore_create(1);
//1 instead of 0 (zero)
Everything (i.e., both for loop and UI) runs immediately and NSLog(@"Loop is Done");
is displayed also immediately, which tells me that semaphore didn't wait here:
dispatch_semaphore_wait(mySemaphore, DISPATCH_TIME_FOREVER);
NSLog(@"Loop is Done");
???
I spent the whole evening trying to figure this out, but to no avail. I hope someone with great GCD knowledge can enlighten me on this.