ようこそゲストさん

色々日記(ざ・めも)

2011/12/27(火) .NETのSerialPortでケーブルを抜くと例外

2011/12/27 13:40 PC(プログラミング)
.NET(WinXP, .NET 3.5で発生)のSerialPortクラスで、USB-Serial変換ケーブルを使用している際に起こる問題。このケーブルに紐づくCOMポートをOpen()後、Close()前にケーブルを抜くと例外が発生する。

原因は.NET側のバグ。ケーブルの挿抜というかCOMポートが消えることを考慮していない。

発生する例外は把握している限りで2種(UnauthorizedAccessException, ObjectDisposedException)。前者は、Dispose()中に発生する。後者は、SerialPort内部で動いてるThreadが出してくる。

UnauthorizedAccessExceptionはラッパークラスを作って、Dispose()をオーバーライドしtry~catchで囲ってやることで対処可能。以下を参照。簡単なのでコードは書かない。

街角のリブロガー: C# SerialPortのエラー「UnauthorizedAccessException」対策

ObjectDisposedExceptionの方はちょっと難しい。発生箇所は.NET内部の別スレッドのようで、捕まえられる場所を思いつかない(存在しない?)しタイミングも不定。Thread.GetDomain().UnhandledExceptionで発生タイミングはとらえられるが、ここではキャンセルできない。古い.NET、おそらく1.1以下だとこの手の例外は処理継続となるのだが、.NET 2.0以降はアプリが落ちてしまう(WinXP/Win7, .NET 3.5で確認)。

ということで、どうもコードでの容易な対処方法がないようだ。アプリケーション構成ファイルでの回避策があるらしいので以下を参照。

SerialPort Crashes after disconnect of USB COM port | Microsoft Connect

こんな感じでよい。

program.cs
[STAThread]
static void Main()
{
	...

	//メインスレッド以外の非ハンドル例外処理
	Thread.GetDomain().UnhandledException +=
		new UnhandledExceptionEventHandler(Application_UnhandledException);

	...
}

public static void Application_UnhandledException(
	object sender,
	UnhandledExceptionEventArgs e
){
	if( e.ExceptionObject != null &&
		e.ExceptionObject.GetType() == typeof(ObjectDisposedException)) {
		
		//.NET3.5のSerialPortのバグで、ケーブル挿抜後にハンドル不能の
		//ObjectDisposedExceptionが返ることがある。このため、未ハンドル例外処理にて
		//ObjectDisposedExceptionについてのみ無視する。

		//何もしない
	} else {
		//何かメッセージを出力
		
		Application.Exit();
	}
}
以下のアプリケーション構成ファイルをアプリケーションと同じディレクトリに置く(hoge.exeが実行ファイルなら、hoge.exe.configとなる)。

hoge.exe.config
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
	<runtime>
		<legacyUnhandledExceptionPolicy enabled="1"/>
	</runtime>
</configuration>
構成ファイルを上記のように書くと、非ハンドル例外に関しては処理継続となる。釈然としないが、どうもこれが楽な方法らしい。

その他の非ハンドル例外を無視して良ければ、program.cs側の記述は不要。

.NETのバージョン変更、OSの変更で直る可能性有り。

1: carcon999 2013年01月14日(月) 午後1時33分

私も同じ問題に遭遇しこの記事で助けられました。ありがとうございました。

2: XP Enbedded 2013年02月08日(金) 午後7時39分

ありがとう、今日一日これで潰れたけど、やっと帰れる。

3: thx 2013年09月05日(木) 午前8時51分

thx!!!

4: sadfd 2014年04月07日(月) 午後5時50分

sadf

5: J 2016年09月01日(木) 午後3時50分

助かりました。4.0でも同様の問題で困りました。


名前:  非公開コメント   

  • TB-URL  http://dt8.jp/cgi-bin/adiary/adiary.cgi/0533/tb/