LoginSignup
2
4

More than 3 years have passed since last update.

Swift Package内のSwiftで並列にタスクを実行する方法

Last updated at Posted at 2020-10-01

とあるきっかけで、UbuntuにSwiftをインストールし、並列処理をやってみたいと思ったのですが、うまくいかなかったのでその問題と解決方法を紹介します。

環境

自分が実行した環境は以下のとおりです。

  • Ubuntu 20.04
  • Swift version 5.3 (swift-5.3-RELEASE)
  • Target: x86_64-unknown-linux-gnu
  • CPU: Ryzen5 2600

やりたいこと

  • とりあえず並列に処理を実行することを確認したい
  • 数字を非同期でprintする

調べたところ、Dispatchqueueを使うのが一般的なようでした。
ProcessThreadなどもあるようですが、Dispatchqueueはそれらを簡単に使えるようにしてものであるようなので、素直にDispatchqueueを使うことにしました。

問題

はじめは調べて出てきたサイトのコードをそのまま写して、以下のようにしていました。

swift package init --type executableを実行して諸々のファイルを生成し、main.swiftを以下のようにしました。

import Foundation

var value: Int = 2

DispatchQueue.main.async {
    for i in 0...3 {
        value = i
        print("\(value) ✴️")
    }
}

for i in 4...6 {
    value = i
    print("\(value) ✡️")
}

DispatchQueue.main.async {
    value = 9
    print(value)
}

しかし、実行結果は

4 ✡️
5 ✡️
6 ✡️
0 ✴️
1 ✴️
2 ✴️
3 ✴️
9

となることが望ましかったのですが、

4 ✡️
5 ✡️
6 ✡️

となってしまいました。
つまり、Dispatchqueueに任せた部分の処理が全く実行されていません。

解決法

この原因には一つ心当たりがありました。
それはファイル単体で動かしていることでした。
多くのサイトはMacで開発しているiPhoneアプリの中で使うことを想定しています。
さらに、Swiftをファイル単体で実行するとき、以前も似たような不具合があったことを覚えていました。以下がそのときに投稿した質問です。
【Swift】Timerで繰り返し実行(定期実行)ができない
これは、アプリの中では自動で実行されるRunLoopがSwiftファイル単体で実行するときには実行されないため、不具合が起きていて、プログラムの末尾にRunLoop.current.run()を追加することで解決しました。
どうようにして今回のプログラムにもRunLoop.current.run()を追加してみました。

import Foundation

var value: Int = 2

DispatchQueue.main.async {
    for i in 0...3 {
        value = i
        print("\(value) ✴️")
    }
}

for i in 4...6 {
    value = i
    print("\(value) ✡️")
}

DispatchQueue.main.async {
    value = 9
    print(value)
}

RunLoop.current.run()

すると期待通りの出力がされました。

まとめ

  • Swiftをアプリではなく、ファイル単体で実行するときにはRunLoopをつけると解決するかもしれない
  • Dispatchqueueを使うときはRunLoopをつけよう

最後に

なにか間違いや改善点がありましたら、コメントや編集リクエストをお願いします。
ありがとうございました。

2
4
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
4