【问题标题】:What language level support (if any) does Swift have for asynchronous programming?Swift 对异步编程有什么语言级别的支持(如果有的话)?
【发布时间】:2014-06-03 09:02:39
【问题描述】:

当应用程序必须通过不可预测的网络(例如智能手机应用程序)进行通信时,异步编程是响应式用户界面的必要条件。用户界面必须在等待结果从 Internet 上某处的服务器返回时保持响应。

在大多数语言中,应用程序程序员必须实现自己的状态机(可能使用闭包)来响应异步回调和/或使用锁协调多个线程。

这两种方法都非常容易出错,不适合既成事实!

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

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

【问题讨论】:

标签: multithreading asynchronous swift


【解决方案1】:

虽然它不是一个内置的语言特性,但注意到 it's possible to implement C# style async/await for Swift 可能会很有趣,并且由于函数调用的最后一个闭包参数提供了特殊语法,它甚至看起来可能成为语言的一部分。

如果有人感兴趣,您可以获取此on 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")
}

【讨论】:

  • 这很好,但坦率地说,这应该是使代码更具可读性的标准。​​
  • 这样安全吗?在 Objective-C 中使用 setjmp/longjmp 与自动释放池(在运行时中作为影子堆栈实现,但不是公共 ABI)发生冲突——据我所知,Swift 也使用自动释放。
  • 在第二个例子中,如果 blk 抛出异常怎么办?
  • @gregswiss 当我最初写这篇文章时,Swift 没有例外。它仍然没有你想的那种例外。另一方面,如果有问题的块抛出了 Objective-C 异常,你就有麻烦了;但对于 Swift 代码来说,这通常是正确的。
  • @pmdj 说得好;就目前而言,它可能不是自动释放安全的。应该可以通过修改自动释放系统使用的 pthread 密钥来修复它,尽管这当然是一个巨大的黑客攻击。我不确定 Swift 是否使用自动释放,FWIW。
【解决方案2】:

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

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

【讨论】:

  • Objective C 有 @synchronization 关键字,所以这似乎不是真的。
  • @Blaze 你的意思是@synchronized?这真的是调用objc_sync_enter()/objc_sync_exit() 的语法糖。如果你愿意,你可以在 Swift 中做到这一点,如果你愿意,你甚至可以添加类似的语法。
  • @synchronized 是一种早于 GCD 的机制,通常被认为不如使用 GCD。值得注意的是,它使用递归锁,这是一种比使用调度队列更昂贵的同步操作
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-03-25
  • 1970-01-01
  • 2013-07-29
  • 1970-01-01
  • 2011-03-29
  • 1970-01-01
  • 2010-09-29
相关资源
最近更新 更多