Basic expressive Swift background thread execution
Yes, I see what you mean: there do appear to be dodgy race conditions. I do like where you are going with this, though – dot syntax and all. Still I found at least one failing test. If you paste your code in a playground and then add the following:

/* your code here */

import XCPlayground
XCPlaygroundPage.currentPage.needsIndefiniteExecution = true

var i = 0

Background {
    i += 1 // don't call `print` here!
}.afterInterval(0) {
    i += 10
}.completion {
    i += 100
}

let t = dispatch_time(DISPATCH_TIME_NOW, Int64(NSEC_PER_SEC))
dispatch_after(t, dispatch_get_main_queue()) {
    print(i)
}

// prints: 101 (instead of 111)


True, delay of 0 seems a little contrived, but it does prove that your worries are founded. One way around this is to trigger a dispatch of those closures on demand (and repeatedly):

import Foundation
class Background {
    let qos: qos_class_t
    let task: (() -&gt; ())?
    private(set) var delay: NSTimeInterval? = nil
    private(set) var delayedTask: (() -&gt; ())? = nil
    private(set) var completionHandler: (() -&gt; ())? = nil

    init(_ qos: qos_class_t = QOS_CLASS_BACKGROUND, task: (() -&gt; ())? = nil) {
        self.qos = qos
        self.task = task
    }

    func delay(interval: NSTimeInterval, task: () -&gt; ()) -&gt; Background {
        self.delay = interval
        self.delayedTask = task
        return self
    }

    func completion(task: () -&gt; ()) -&gt; Background {
        self.completionHandler = task
        return self
    }

    func async() {
        dispatch_async(dispatch_get_global_queue(qos, 0)) { // TODO: unnecessary if `task == nil` 
            self.task?()
            if let delayedTask = self.delayedTask, let delay = self.delay {
                let t = dispatch_time(DISPATCH_TIME_NOW, Int64(delay * NSTimeInterval(NSEC_PER_SEC)))
                dispatch_after(t, dispatch_get_main_queue(), delayedTask)
            }
            if let completionHandler = self.completionHandler {
                dispatch_async(dispatch_get_main_queue(), completionHandler)
            }
        }
    }
}


Which can be used like so:

import XCPlayground
XCPlaygroundPage.currentPage.needsIndefiniteExecution = true

var i = 0

let bg = Background {
    i += 1
}.delay(0) {
    i += 10
}.completion {
    i += 100
}

// nothing dispatched yet!

bg.async() // repeated invocations possible
bg.async()

Background().delay(1) {
    print(i)
}.async()

// prints: 222 (as it should)


In addition, I would probably rename Background...