Hatena::ブログ(Diary)

菊やんの雑記帳

2007-03-13 SynchronizationContext

[] 01:27 SynchronizationContext - 菊やんの雑記帳 を含むブックマーク

去年の三月にmixiに書いた日記なのだが需要がありそうなので、いまさらながらここにこぴぺ

SynchronizationContext

.NET2.0で追加されたクラス。

ネットワークを使うGUIアプリはたいがい裏で仕事をしてるスレッドがあって、構成的には表の部分と裏の部分にばっちり分かれそうなものなのだが、裏で起きたイベントをGUIイベントハンドラで処理するにはどうするかというと、

WIN32ならPostMessageでメッセージを送る。

.NET1.1ならControl.BeginInvokeを使う。(内部でPostMessageでは呼んでるはず)。

ということは、裏の仕事をやるコンポーネントにはウィンドウハンドルとか、Control オブジェクトとかを最初に渡さないといけないわけだ。

で、.NET2.0ならBackgroundWorkerやAsyncOperationを使ってやると簡単にできる。前者は裏の作業の完了や進捗の報告に特化したクラスで、後者はどんなイベントでもGUI側に報告できるPostというメソッドをもっている。当然、前者は後者を用いて実装されている。

ここで不思議なことに、これらのクラスはウィンドウハンドルとかControlオブジェクトを渡す必要がないということだ。ということは何か裏で知らない機能を使っているということなので、調べてみると、SynchronizationContextというものが重要であることがわかった。

.NET2.0ではスレッドごとにSynchronizationContextのオブジェクトを持っていて、SynchronizationContext.Currentで読める。フォームを作ったときには自動でControl.Invokeを呼ぶオブジェクトが設定されているということだった。裏のコンポーネントが表のイベントを発生させるためのインターフェースをちゃんと定義したってことだな。

メッセージポンプがないような、コンソールアプリケーションでも、適切にメッセージキューを作って、適当なSynchronizationContextの実装を設定すれば、このイベントモデルが使えるようになるということか。

某 2007/03/14 07:51 Javaだと、mainの中でSwingUtilities#invokeLaterを使ってFrame(のサブクラス)のコンストラクタを呼び出すのを見たことがあるなぁ