Swift对异步编程有哪些语言级别的支持(如果有的话)?

18

异步编程对于需要在不可预测网络上通信的应用程序来说是响应式用户界面的必备技术(例如智能手机应用程序)。在等待来自互联网某处的结果返回时,用户界面必须保持响应。

在大多数语言中,应用程序员必须实现自己的状态机(可能使用闭包)来响应异步回调和/或使用锁协调多个线程。这两者都非常容易出错,不适合心脏脆弱的人!

(C#引入了async关键字来帮助解决此问题,只有时间(至少5年)才能证明它是否是一个好的解决方案.)

Swift是否有任何内置支持来协助编写异步代码?


2个回答

13

虽然这不是一种内置的语言特性,但值得注意的是可以为Swift实现类似于C#的async/await, 并且由于在函数调用的最后一个闭包参数中提供了特殊的语法,它甚至看起来可能是该语言的一部分。

如果有人感兴趣,可以在Bitbucket上获取此代码。以下是一些可能性的快速示例:

let task = async { () -> () in
  let fetch = async { (t: Task<NSData>) -> NSData in
    let req = NSURLRequest(URL: NSURL.URLWithString("http://www.google.com"))
    let queue = NSOperationQueue.mainQueue()
    var data = NSData!
    NSURLConnection.sendAsynchronousRequest(req,
                                            queue:queue,
      completionHandler:{ (r: NSURLResponse!, d: NSData!, error: NSError!) -> Void in
        data = d
        Async.wake(t)
      })
    Async.suspend()
    return data!
  }

  let data = await(fetch)
  let str = NSString(bytes: data.bytes, length: data.length,
                     encoding: NSUTF8StringEncoding)

  println(str)
}

另外,如果你想要类似于@synchronized的功能,请尝试以下代码:

func synchronized(obj: AnyObject, blk:() -> ()) {
  objc_sync_enter(obj)
  blk()
  objc_sync_exit(obj)
}

var str = "A string we can synchronise on"

synchronized(str) {
  println("The string is locked here")
}

1
这很不错,但说实话应该是标准的,以使代码更易读。 - Blaze
这样做安全吗?在 Objective-C 中使用 setjmp/longjmp 与自动释放池产生冲突(它们作为运行时中的影子堆栈实现,但不是公共 ABI)- 就我所知,Swift 也使用自动释放机制。 - pmdj
1
在第二个例子中,如果blk抛出异常会怎么样? - gregswiss
@gregswiss 当我最初编写这个时,Swift还没有异常处理。它仍然没有你想要的那种异常处理方式。另一方面,如果问题中的块引发Objective-C异常,那么你就有麻烦了;但这通常适用于Swift代码。 - al45tair
@pmdj 那是个好观点;就目前而言,它可能不是autorelease安全的。通过调整autorelease系统使用的pthread key,应该可以修复它,尽管这当然是一个巨大的hack。就我所知,Swift是否使用autorelease还不确定。 - al45tair

11

Swift对于异步编程的方法与Objective C相同:使用Grand Central Dispatch。您可以像在ObjC中一样将闭包传递给gcd dispatch_函数。但是,出于美学原因,您还可以在关闭括号后传递闭包(块):

dispatch_async(dispatch_get_main_queue()) {
    println("async hello world")
}

Objective C有@synchronization关键字,因此这似乎不是真的。 - Blaze
@Blaze 你是指 @synchronized 吗?那只是调用 objc_sync_enter()/objc_sync_exit() 的语法糖。如果你愿意,你可以在 Swift 中这样做,甚至可以添加类似的语法。 - al45tair
@synchronized 是一种早于 GCD 的机制,通常被认为不如使用 GCD。值得注意的是,它使用递归锁,这是一种比使用调度队列更昂贵的同步操作。 - Lily Ballard

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接