2013年11月2日土曜日

BackGroundWorkerによる別スレッドからUIクラスにアクセスする

過去記事にて、C#でマルチスレッドを実現するBackGroundWorkerというコンポーネントを紹介しました。スレッドクラスを利用した処理に比べてシンプルなコードになる利点がありましたが、実際に使ってみてさらなる利点に気づきました。

マルチスレッド処理のUIアクセスの制約
マルチスレッド処理をする際の困難さの1つに、プロセス間通信の制約があります。つまり、スレッドが異なる処理のデータの授受には制約があるということです。この制約の影響をモロに受けるのが、UIコンポーネントです。起動したスレッドから呼び出しものにあるUIコンポーネントにデータを渡す、、例えば、ラベルに値を表示するなどの処理は原則できません。Invorker経由でメソッドを呼び出さないといけません。これでなんら問題なければいいんですが、先日、某サードパーティ製のUIクラスを利用する時に、うまく呼び出すことができませんでした。正確に言うと、Invorker経由で呼び出すと動作が異常に遅くなるのです。もともとthreadクラスを利用していたのでその時は問題なかったのですが、今回、BackgroundWorkerを利用するとダメという、、、意味不明なことに。。。

ProgressChangedイベントが肝!
で、ネットをいろいろ調べてみると、ProgressChangedイベント内ではInvokerが不要であるということが判明しました。正直理屈のわからない話ですが、実際に試してみると、InvorkerなしでUIクラス(Labelクラス)にアクセスすることができました。ProgressChangedイベントを呼び出すためには、
  • WorkerReportsProgressプロパティをtrueにしておく
  • ReportProgressメソッドを呼び出す
という手順が必要です。この方法により、Invorkerを使わなくてよく、さらにUIへの処理を分離できるので、コード的にスッキリします。


0 件のコメント:

コメントを投稿