これは増えすぎた地球の人口よりも多くのデバイスで走るCOMポートをC#などで操作しようとしたとき、割としばしば起こる"有効ではないスレッド間の操作"例外の回避方法についての補足である。
一般にはレガシーデバイスとみなされるCOMポートであるが、このデバイスは産業用途では今でも十分現役である。さまざまな機器がRS-232CやRS-485によるリモートコントロールをサポートしているので今でもSerialPortクラスの恩恵にあずかっているプログラマーは少なくない。
ところでSystem.IO.Ports.SerialPortクラスが発生させるDataReceivedイベントは次のような説明になっている。
DataReceived からデータを受信すると、セカンダリ スレッドでイベントが発生する、 SerialPort オブジェクトです。このイベントは、セカンダリ スレッドで発生されるため、メイン スレッドではなく、UI 要素など、メイン スレッドの一部の要素を変更しようとしています。 スレッド処理、例外を発生させる可能性があります。メイン ページでの要素を変更する必要がある場合は、 Form または Control, 、投稿の変更要求を使用して Invoke, 、これは適切なスレッドで処理を行います。
お分かりいただけただろうか。Control.Invokeメソッドが回避方法として提案されているが、この方法はWindows.Formsに依存しているのでWPFなどを使用している場合には採用しにくいのである。
この問題をより抜本的に解決するにはSystem.Threading.SynchronizationContextクラスなどが使用できる。クラス名で検索すれば詳しい仕組みや使い方はいくらでも出てくる†‡のでここでは割愛するが、要はSynchronizationContextオブジェクトを事前にメインスレッドで生成しておいて、これにイベントハンドラの中身のうちメインスレッドに依存するオブジェクトに対する処理を委譲すればいい。