concurrency (dispatchqueue) test isn't going as expected ios/swift - ios

So I have this code in a Swift 4 playground:
//: Playground - noun: a place where people can play
import UIKit
import PlaygroundSupport
PlaygroundPage.current.needsIndefiniteExecution = true
DispatchQueue.main.async {
for _ in 1...5 { print("Main") }
}
DispatchQueue.global().async {
for _ in 1...5 { print("Background") }
}
DispatchQueue.global(qos: .userInteractive).async {
for _ in 1...5 { print("User Interactive") }
}
Why does this print out:
User Interactive
Background
Background
User Interactive
User Interactive
Background
User Interactive
Background
User Interactive
Background
Main
Main
Main
Main
Main
I understand why the "User Interactive" and "Background" are printing out in a random order, but why is "Main" printing out after? Shouldn't it be prioritized because it's in the main queue? I guess I still don't fully understand how GCD and QOS works in Swift 4.
EDIT
I now added these two print outs and a few lines:
print("BEGINNING OF CODE")
DispatchQueue.main.async {
for _ in 1...5 { print("Main") }
}
DispatchQueue.global().sync {
for _ in 1...5 { print("Sync Global") }
}
DispatchQueue.global(qos: .background).async {
for _ in 1...5 { print("Background") }
}
DispatchQueue.global(qos: .userInteractive).async {
for _ in 1...5 { print("User Interactive") }
}
print("END OF CODE")
And it prints this out:
BEGINNING OF CODE
Sync Global
Sync Global
Sync Global
Sync Global
Sync Global
END OF CODE
User Interactive
Background
User Interactive
User Interactive
User Interactive
User Interactive
Background
Background
Background
Background
Main
Main
Main
Main
Main
My question now is: shouldn't the background queues be printed out before the "END OF CODE"? If the last two blocks were enqueued and immediately started executing, why aren't they printing out before? Is it because the main queue has a higher priority? But shouldn't it run asynchronously?

The code in the playground is being run on the main queue. So the first for loop is enqueued on the main queue and it won't be run until the end of your code is reached.
The other two blocks are enqueued onto background queues and can start running immediately.
The code you have running on the background queues is so simple and quick that it happens to finish before the first block has a chance to run.
Add a sleep inside one of the two background blocks and you will see that the "Main" output comes out sooner. Your test gives misleading results because it is to simple and too fast.

Global queues are non FIFO type.. They occupy a thread soon as they find one that is available. Thats why they run faster..
The main queue task runs serially on main thread.. usually called from background when UI needs updation

Related

How do I perform background tasks while blocking the caller

I'd like to create a function that performs multiple background operations but the caller should not be aware of its asynchronous nature. So when a caller calls that function it should block the caller's thread and continue after it finishes all the tasks.
Ideally, the function should be called by just invoking its name (say blockingFunction()).
How do I achieve that?
(The main thread isn't a concern here)
We will posit the following test method:
func test() {
print("start")
self.doYourThing()
print("finish")
}
That function is internally synchronous: it proceeds one line at a time from start to finish.
We also have an asynchronous method using an old-fashioned completion handler:
func behaveAsynchronously(completion: #escaping () -> ()) {
DispatchQueue.global().asyncAfter(deadline: .now()+10) {
completion()
}
}
We will consider the problem solved if doYourThing somehow calls behaveAsynchronously and yet "finish" prints 10 seconds after "start". Ready? Here we go:
func doYourThing() {
let group = DispatchGroup()
group.enter()
self.behaveAsynchronously {
group.leave()
}
group.wait()
}
QED.
Note that we are blocking the main thread for 10 seconds, which is illegal; if you did that in real life, you'd crash. Also, there must be multiple threads in the story, or we would be attempting to wait on the same thread we are delayed on and a deadlock results.

dispatch sync vs dispatch async in main queue ios related query

so what I understood from basics is:
the async task will not block the current queue, sync task will block the current queue until that task finishes.
but when I run code on the main queue, just to print number from 1 to 100, it is giving me the same output.
use case -1
DispatchQueue.global(qos: .default).async {
DispatchQueue.main.async {
for i in 0...100{
print(i)
sleep(arc4random() % 5)
}
}
}
==============
use case -2
DispatchQueue.global(qos: .default).async {
DispatchQueue.main.sync {
for i in 0...100{
print(i)
sleep(arc4random() % 5)
}
}
what can be the reason for getting the same output for async vs sync on the main queue?
Is it because the serial queue will have only one thread associated with it?
When you, a queue, say DispatchQueue.main.sync or DispatchQueue.main.async, that does not affect how the main queue behaves; it affects how you behave, ie whether you wait before doing what comes after the call. But you have nothing after the call so there is no distinction to draw. Your “test” does not test anything.

Run Two Loops Parallely in iOS Swift

Is it possible to run two While loops parallely in Swift Programming Languages. Both of the loops are independent but both are heavy process going.
Is it possible to run two loops at a time
Yes it's possible. You just have to run both loops on separate threads.
It's general rule: If you want to run two processes in the same time, you have to run them separately.
Example code which you can just copy and paste to playground to see how it works:
//DispatchQueue(label: "com.app.queue1", qos: .background).async {
DispatchQueue.global(qos: .background).async {
while true {
print(1)
sleep(1)
}
}
//DispatchQueue(label: "com.app.queue2", qos: .background).async {
DispatchQueue.global(qos: .background).async {
while true {
print(2)
sleep(1)
}
}
... you can also use just main thread and one background. It depends on what you need. But the main idea is the same, you have to have separate threads.
You can call it in 2 separate background threads.
DispatchQueue.global(qos: .background).async {
// function 1
}
DispatchQueue.global(qos: .background).async {
// function 2
}
Since these are background threads, if you want to do, then do something in the main thread, you'll have to switch to the DispatchQueue.main.
If you want to run them on 2 separate queues, you can make them something like
let backgroundQueue = DispatchQueue(label: "loadQueueOne", qos: .background)
backgroundQueue.async {
// function 1
}
You can similarly create another one, separate, for the second queue.

NSAsynchronousFetchRequest - should update be explicitly done on main thread

I am creating an NSAsynchronousFetchRequest which has a completion block inside it.
I have seen various examples where some include using dispatch queue on the main thread and others don't. For example the Ray Wenderlich core data book doesn't call the result on the main thread.
Should I go back on the main thread when executing the result. Initially I thought I had to but now I don't. Some definitive clarity would be great.
fun exampleFetch(_ completionHandler: #escaping () -> () {
let fetchRequest = NSFetchRequest<NSDictionary>(entityName: "Example")
let asyncFetchRequest = NSAsynchronousFetchRequest<NSDictionary>(fetchRequest: fetchRequest) { result in
// DispatchQueue.main.async { // is this needed
completion()
//}
}
managedContext.performChanges {
do {
try self.managedContext.execute(asyncFetchRequest)
} catch let error {
print("error trying to fetch saving objects:", error.localizedDescription)
}
}
}
You should not explicitly call the completion handler on the main queue. Let the caller decide how to handle it. If anything, document that the completion handler will be called on an arbitrary queue. Then the client calling your exampleFetch method knows that it is their responsibility to be sure that process the result on whatever queue it needs.
This gives the client more control.
This also prevents a lot of needless thread switching. A client may call exampleFetch from a background queue and it may want to process the results in the background. If you explicitly put the completion on the main queue, the client then needs to explicitly switch back to a background queue to process the result. That's two needless queue switches and it's wasted effort on the main queue.

Is it normal that CPU usage exceeds 100% using dispatch async in Xcode 7

I'm a beginner in swift 2, and I'm trying to make my program blocks while showing only a progress spinner until some operation finishes, I made that code snippet in a button with the action "touch up inside", my problem is that while debugging,Xcode 7 CPU usage jumps to 190 % once I tap my button and keeps high until the flag changes its value, Is it normal that CPU usage jumps like that?, also Is it a good practice to use the following snippet or shud i use sleep or some other mechanism inside my infinite loop?
let queue2 = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)
dispatch_async(self.queue2) { () -> Void in
while(flag == true)
{
//wait until flag sets to false from previous func
}
self.dispatch_main({
//continue after the flag became false
})
This is a very economical completion handler
func test(completion:() -> ())
{
// do hard work
completion()
}
let queue2 = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)
dispatch_async(queue2) {
test() {
print("completed")
}
}
or with additional dispatch to the main queue to update the UI
let queue2 = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)
dispatch_async(queue2) {
test() {
print("completed")
dispatch_async(dispatch_get_main_queue()) {
// update UI
}
}
}
This is totally wrong approach as you are using while loop for waiting. You should use Completion Handler to achieve this kind of stuff.
Completion handlers are callbacks that allow a client to perform some action when a framework method or function completes its task. Often the client uses a completion handler to free state or update the user interface. Several framework methods let you implement completion handlers as blocks (instead of, say, delegation methods or notification handlers).
Refer Apple documentation for more details.
I suppose you have a sort of class which manages these "some operation finishes".
When you finish your operations you can comunicate by completion handler or delegation. In the meanwhile you can disable the user interaction of your UI until the end of these operations.
If you provide more informations about your background operations I can add some snippets of code.

Resources