I created a basic background thread class in swift to replace the ugliness of:dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) { () -> Void in  // background thread code  dispatch_async(dispatch_get_main_queue()) { () -> Void in      // done, back to main thread  }}with the expressiveness of:Background { () -> () in    // background code  }.afterInterval(3) { () -> () in    // main thread, run after interval IF not done  }.completion { () -> () in    // done, main thread  }afterInterval and completion are optional and interchangeable.How reliable is this approach? Can we ever return from init(task) before completion is added, using the dot syntax? I have tested to my abilities and it seems rather bulletproof, but am wondering about the thoughts here.class Background {  private var done = false {    didSet {      if done {        taskInterval = nil        dispatch_async(dispatch_get_main_queue()) { () -> Void in          completion?()        }      }    }  }  private var taskInterval: (() -> ())?  private var completion: (() -> ())?  init(task: () -> ()) {    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) { () -> Void in      task()      self.done = true    }  }  func afterInterval(interval: NSTimeInterval, closure: () -> ()) -> Background {    taskInterval = closure    let delayTime = dispatch_time(DISPATCH_TIME_NOW, Int64(interval * Double(NSEC_PER_SEC)))    dispatch_after(delayTime, dispatch_get_main_queue()) { [weak self] in      self?.taskInterval?()    }    return self  }  func completion(closure: () -> ()) -> Background {    completion = closure    return self  }}SwiftyThreads on Github
Basic expressive Swift background thread execution
multithreading;swift
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 XCPlaygroundXCPlaygroundPage.currentPage.needsIndefiniteExecution = truevar i = 0Background {    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 Foundationclass Background {    let qos: qos_class_t    let task: (() -> ())?    private(set) var delay: NSTimeInterval? = nil    private(set) var delayedTask: (() -> ())? = nil    private(set) var completionHandler: (() -> ())? = nil    init(_ qos: qos_class_t = QOS_CLASS_BACKGROUND, task: (() -> ())? = nil) {        self.qos = qos        self.task = task    }    func delay(interval: NSTimeInterval, task: () -> ()) -> Background {        self.delay = interval        self.delayedTask = task        return self    }    func completion(task: () -> ()) -> 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 XCPlaygroundXCPlaygroundPage.currentPage.needsIndefiniteExecution = truevar i = 0let bg = Background {    i += 1}.delay(0) {    i += 10}.completion {    i += 100}// nothing dispatched yet!bg.async() // repeated invocations possiblebg.async()Background().delay(1) {    print(i)}.async()// prints: 222 (as it should)In addition, I would probably rename Background...