2011-08-21

どのNSThreadにでもperformSelector:onThread:する


iOSには performSelector:onThread:withObject:waitUntilDone: という非常にすばらしいAPIがある。指定のスレッド上でレシーバーのセレクタを実行してくれるのだ。

だからメインスレッドでUI処理をしているインスタンスなんかから、ちょっとこの重い処理やっといててな感じで別スレッドに処理を投げるのが、ものすごく簡単にできる。

waitUntilDone: のYES NO指定だけで同期・非同期も簡単に選べる。

ただし、そのスレッドでランループが回っていなければならない、という条件が付く。
このランループってのは概念としてはイベントディスパッチャであり、複数ある入力ソースのどれかが準備できるまで寝て待ちソースが発火したら取り出して処理の無限ループというフレームワークになってる。
で、入力ソースがひとつも無いとランループはループを抜けて終了してしまう。
だから単にスレッドを起動しただけではダメで、スレッド上でランループをランしただけでもダメなのだ。

このあたりを考慮にいれて、
  1. スレッドを作成して
  2. 発火しないダミーの入力ソースを一個ランループに取りつけて
  3. ランループを回して別スレッドからの performSelector:... を待つ
ということをやってみた。
これならばいつでも performSelector:onThread: で投げた処理を受けつけてくれる。

コードはgithubに。

NSOperation使ったらどうかと思うかもしれない。このクラスは細粒度の並列では使いやすいけど、長期間生きてるリソースをもとにしたバックグラウンドサービス的な並列では制御が逆にしづらいんだよな。

0 件のコメント: