3

I'm trying to understand how Swift 4.0 asynchronous processing works in Linux.

After looking at the documentation and some answers on SO I came up with this simple example:

import Dispatch
import Glibc

DispatchQueue.main.asyncAfter(deadline: .now()) {
    print("Done!")
}

print("Sleeping for 2 seconds...")
usleep(2 * 1_000_000)

print("Exiting...")

However, this only prints:

Sleeping for 2 seconds...
Exiting...

Why does it not print Done!? What am I missing? How do I write a simple parallel processing example?

naktinis
  • 3,957
  • 3
  • 36
  • 52

3 Answers3

2

You have to call dispatchMain() to start the GCD event loop:

Executes blocks submitted to the main queue

Example:

DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
    print("Done!")
    exit(0)
}

print("Starting main event loop...")
dispatchMain()
Martin R
  • 529,903
  • 94
  • 1,240
  • 1,382
  • Where should I add it in my example above? If I add it after `.asyncAfter{...}`, it prints "Done!", but then does not continue executing other statements and doesn't print "Sleeping..." or "Exiting...". – naktinis Feb 03 '18 at 14:55
  • @naktinis: That is correct, dispatchMain never returns. You have to `exit(0)` the program somewhere. – Martin R Feb 03 '18 at 15:30
0

I think the problem was using the main queue. If I instead create a new queue, it works as expected.

import Dispatch
import Glibc

DispatchQueue(label: "worker").asyncAfter(deadline: .now()) {
    print("Doing work...")
    usleep(1 * 1_000_000)
    print("Work done")
}

print("Sleeping for 2 seconds...")
usleep(2 * 1_000_000)

print("Exiting...")

Prints out the expected result:

Sleeping for 2 seconds...
Doing work...
Work done!
Exiting...
naktinis
  • 3,957
  • 3
  • 36
  • 52
0

Dispatch is not preemptive. Blocks that are submitted to a non-concurrent queue will be processed in order, and no block will be processed until the block before them finishes. You put your block on the main queue, which corresponds to the main thread, however, the main thread is busy sleeping until it exits, and never has a chance to do dispatch queue work.

Martin R mentioned dispatchMain, though another option would be RunLoop.main.run(mode: .defaultRunLoopMode, before: .distantFuture), which would only run the runloop once, allowing the program to exit afterwards.

TellowKrinkle
  • 351
  • 3
  • 5