スレッドに悩まされるの巻

GPSを受信して適宜イベントを出すというのをやろうとしていて、最初は .net compact framework 2 でやってたのですが、過去のイキサツのため、dnfw 1 でやり直す。
と、COMM関係のコンポーネントが存在しませんでした。気付けよ…。
ということで、P/Invokeを使い CreateFile() でポートを開いて、ReadFile() で適当なサイズのByte配列のバッファに読み込み、行ごとに切り出して、文字列にして、splitして、位置情報を受信できてたら(NMEAフォーマットについては id:yellow_73:20050603 にリンクあり)、イベントを発生させ、バッファのデータが尽きたらまた ReadFile() を実行する、というループを繰り返すルーティンを実行します。なお、このルーティンは、(マネージド)スレッドを新しく作って実行させます。
ここで問題になるのが、スレッドセーフにすること。アンセーフのままだと、paintイベントとかのハンドリング時に原因不明(アンセーフなのが原因なので本当は原因不明じゃないです)のロックがかかります。
dnfw 2 だと、InvokeRequired → Invoke をやっていきます。また、フォームごとにこの定型的な手続きを実装するのは面倒くさいので、GPS受信機能はコントロールにして、Invokeできるようにしました。
dnfw 1 の場合、InvokeRequired が無いので、これは無視して、Invoke のみを実行でいいみたい。
compact framework の場合、さらに機能縮小されていて、Invokeで指定するメソッドに引数を渡せません。
で、compact frmework で、自前で delegate を作って Invoke に渡すと失敗しました。ArgumentException が出て、しかも原因が全く書かれていませんでした。
困ったので、なんとなく EventHandler という delegate で渡すようにしたらうまくいきました。
メソッドの引数は ( sender as object, e as EventArgument) で固定です。また、イベント引数は渡せません(受ける方は Nothing になります)。引数を渡したい場合は、メンバ変数に押し込んでから Invoke を実行するしかないみたいです。