非同期処理

編集

DispatchQueue

編集
import Dispatch

let NMAX = 100

DispatchQueue.global(priority: .low).async {
  var n = 1.0
  var e = 1.0
  for i in 1...NMAX {
    n *= Double(i)
    e += 1.0 / n
    print("e(\(i)) = \(e)")
  }
}

DispatchQueue.global(priority: .low).async {
  var pm = -1.0
  var pi = 0.0
  for i in 0...NMAX {
    pm *= -1
    pi += pm * 4 / (2 * Double(i) + 1)
    print("pi(\(i)) = \(pi)")
  }
}

遅延実行

編集
import Dispatch

let semaphore = DispatchSemaphore(value: 0)

DispatchQueue.global(priority: .low).async { // すぐに実行
  print("executed now")
  semaphore.signal()
}
semaphore.wait()

DispatchQueue.global(priority: .low).asyncAfter(deadline: .now() + 1) { // 1秒後に実行
  print("executed 1 second later")
  semaphore.signal()
}
semaphore.wait()

DispatchGroup

編集
import Dispatch

let NMAX = 10000

let group = DispatchGroup()

let queue1 = DispatchQueue.global(priority: .low)
queue1.async(group: group) {
  var n = 1.0
  var e = 1.0
  for i in 1...NMAX {
    n *= Double(i)
    e += 1.0 / n
    print("e(\(i)) = \(e)")
  }
}

let queue2 = DispatchQueue.global(priority: .low)
queue2.async(group: group) {
  var pm = -1.0
  var pi = 0.0
  for i in 0...NMAX {
    pm *= -1
    pi += pm * 4 / (2 * Double(i) + 1)
    print("pi(\(i)) = \(pi)")
  }
}

group.wait()
print("queue finished")

DispatchSemaphore

編集
import Dispatch

let NMAX = 10000

let semaphore = DispatchSemaphore(value: 0)
DispatchQueue.global(priority: .low).async {
  for i in 0..<NMAX {
    print(i)
  }
  semaphore.signal()
}

print("before waiting")
semaphore.wait() // この1行を外すと、NMAXまで出力される前に次の行に進む
print("after waiting")

async/await (Swift 5.5以降)

編集

Swift 5.7以降(Task.sleep使用可能)

import Foundation

let semaphore2 = DispatchSemaphore(value: 0)

func asyncTaskCore(n:Int) async {
  try! await Task.sleep(for: .seconds(1))
  print("asyncTaskCore(\(n)) done")
}

func asyncTask() async {
  await asyncTaskCore(n: 0) // コールバック関数の場合との比較のため、あえてfor文不使用
  await asyncTaskCore(n: 1)
  await asyncTaskCore(n: 2)
  await asyncTaskCore(n: 3)
  await asyncTaskCore(n: 4)
}

Task {
  await asyncTask()
  semaphore2.signal()
}
semaphore2.wait()

Swift 5.5.x~5.6.x

import Foundation

let semaphore2 = DispatchSemaphore(value: 0)

func asyncTaskCore(n:Int) async {
  let semaphore1 = DispatchSemaphore(value: 0)
  DispatchQueue.global(priority: .low).asyncAfter(deadline: .now() + 1) {
    semaphore1.signal()
  }
  semaphore1.wait()
  print("asyncTaskCore(\(n)) done")
}

func asyncTask() async {
  await asyncTaskCore(n: 0)
  await asyncTaskCore(n: 1)
  await asyncTaskCore(n: 2)
  await asyncTaskCore(n: 3)
  await asyncTaskCore(n: 4)
}

Task {
  await asyncTask()
  semaphore2.signal()
}
semaphore2.wait()

Swift 5.4.x以前(コールバック関数使用)

import Foundation

let semaphore2 = DispatchSemaphore(value: 0)

func asyncTaskCore(n:Int, callback:() -> ()) {
  let semaphore1 = DispatchSemaphore(value: 0)
  DispatchQueue.global(priority: .low).asyncAfter(deadline: .now() + 1) { 
    semaphore1.signal()
  }
  semaphore1.wait()
  print("asyncTaskCore(\(n)) done")
  callback()
}

func asyncTask(callback:@escaping () -> ()) {
  asyncTaskCore(n: 0, callback: {
    asyncTaskCore(n: 1, callback: {
      asyncTaskCore(n: 2, callback: {
        asyncTaskCore(n: 3, callback: {
          asyncTaskCore(n: 4, callback: {
            callback()
          })
        })
      })
    })
  })
}

asyncTask(callback: {
  semaphore2.signal()
})
semaphore2.wait()


外部リンク

編集