<< Prev Page Next Page >>

スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。


マルチスレッドの反省

お仕事でiPadアプリを作った。画面をいろいろ操作してる間にも裏でスレッドが走ってて定期的にどのファイルをダウンロードするか判定して必要なファイルをダウンロードしたりするやつ。それだけなら別になにも難しくないんだけど、ファイルごと+ファイル群ごと+全体の3種類のプログレス表示とダウンロードが終わったら画面表示をがさっと変更する仕様があったのを甘く見てた。



ダウンロードだけでなくXMLを読み込んでDBに登録したりとかいろいろしてからイベントが上がって画面表示を変更するような作りにしてしまったため、出るわでるわEXC_BAD_ACCESS。

アニメーションして画面遷移したあとイベントリスナを解除してからUIViewControllerをreleaseし終わってるのに、ダウンロードスレッドのほうでイベントループの途中になってしまっているため、zombieオブジェクトに対するメッセージになってしまってEXC_BAD_ACCESSであぼーん。そらそうなるわな。

この程度の設計で間違うとはまだまだだ自分。

反省として、次回こういうものを作る機会があったらこういうつくりにすること、というのを備忘録として書いておこう。

[大方針]
・バックグラウンドスレッドから呼ばれるイベントリスナで画面に関わるAPIを呼ばない。iOSアプリはアニメーションによる遅延実行が多いのでハマる原因になる。
・挙動がカクカクしないよう、負荷を増やさないよう、@synchronizedの箇所を最小限にする、というか、意味的にatomicでなければならないことを表現する以外で@synchronizedを使わない。

[小方針]
・イベントリスナの処理ではModelを変更したり変更フラグをたてたりするだけにする
・画面描画が必要な場面ではNSTimerで0.1秒ごととかの定期実行スレッドを一つ動かしておいて、変更フラグを見て描画範囲を確定して、Modelのデータを取得して表示する。このときModelが変更途中の場合は待つのではなくスルーして次回定期実行時に参照すればよい。
・バックグラウンドスレッドが無駄に増えて行かないように、あらかじめダウンロード用ワーカスレッドを2つとか立ち上げておいて、ダウンロード開始するときはそのスレッドに依頼するようにする
・イベントリスナの処理中でイベントリスナの追加削除を行わない
・SQLiteのコネクションはopenしっぱなしでシングルトンを使い回す
・DBのトランザクション処理だけは@synchronizedで囲む

もう一度結城浩さんのマルチスレッドデザインパターンを読む。


この記事に対するコメント

この記事に対するコメントの投稿



管理者にだけ表示を許可する

この記事に対するトラックバック

トラックバックURL
http://tockri.blog78.fc2.com/tb.php/256-ed6f7a77
この記事にトラックバックする(FC2ブログユーザー)

上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。