2009年10月21日水曜日

C# SerialPortのエラー「UnauthorizedAccessException」対策

「UnauthorizedAccessException」
このエラーはUSB-シリアルケーブルを使っていて、
ケーブルが抜かれた時に発生します。

デバッガで問題箇所まで簡単に追跡できるけど、
Try~catch文で囲ってもCatchした後に、プログラムが終了してしまう。
さて、困った。

この問題の原因は、
ファイナライザ内で発生する未処理の例外は、アプリケーション側でキャンセルする事はできない事。

つまり、ファイナライザの中で例外が発生しないように実装すればいいので、
解決策はエラー発生したコンポーネントクラス(SerialPort)を継承して、
その中で「UnauthorizedAccessException」エラー処理を実装すればいい。

具体的には、
SerialPortクラスを継承したクラス内で
アタッチ・デタッチ処理を実装、COMポートの定期チェックとDispose時に行う方法を取る。する。
@2011.02.28 修正
COMポートの定期チェックは継承クラス外で行う。(やっておくと安全)


下記継承クラスを使って、Serialコンポーネントと置き換えてやればよい。
/// 
/// USBタイプのシリアルポートを抜くとアプリケーションが異常終了する現象を
/// 回避するための SerialPort 継承クラス
/// 
public class SafeSerialPort : System.IO.Ports.SerialPort
{
    bool userOpen = false;
    System.IO.Stream SafeBaseStream = null;

    public new void Open()
    {
        base.Open();
        userOpen = true;
        SafeBaseStream = this.BaseStream;
    }

    protected override void Dispose(bool disposing)
    {
        if (userOpen && base.IsOpen == false)
        {
            // 予期せず COM ポートが閉じている
            try
            {
                userOpen = false;
                if (disposing)
                {
                    SafeBaseStream.Close();
                }
            }
            catch(UnauthorizedAccessException)
            {
                // 必ず例外が発生するが 無視する
            }
        }
        base.Dispose(disposing);
    }
}

0 件のコメント:

Androider