質問者
実装すべき例外処理について教えてください

質問
-
.NET初心者、マネージコード初心者(というのでしょうか?)です。
現在、PCとPHS端末をUSBで接続し、COMポートを使用してATコマンドを端末へ通知し、制御するアプリケーションを作成中です。ATコマンドとは、文字列ベースの制御用コマンドで、一般にはターミナルソフト等を使用することでATコマンドを端末へ通知します。
一言で言えば、「シリアルポートを使用した文字列のやり取り」を実装する訳で、おおまかな所までは出来ていますが、例外処理を記述できずに困っています。
以下、実装コードです。
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO.Ports;namespace SerialPortResearch1
{
public partial class Form1 : Form
{
private delegate void AppendMessageDelegate(string mes);
public Form1()
{
InitializeComponent();
}private void button1_Click(object sender, EventArgs e) //ポートの設定+オープン
{
this.serialPort1.PortName = this.textBox1.Text;
this.serialPort1.BaudRate = 115200;
this.serialPort1.Parity = Parity.None;
this.serialPort1.DataBits = 8;
this.serialPort1.StopBits = StopBits.One;
this.serialPort1.Open();
}private void Form1_Load(object sender, EventArgs e) //シリアルポートクラスの初期設定
{
this.serialPort1.NewLine = "\r\n";
this.serialPort1.DataReceived += new SerialDataReceivedEventHandler(SerialPort_DataReceived);
this.serialPort1.DtrEnable = true;
this.serialPort1.RtsEnable = true;
}private void SerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e) //文字列受信イベント
{
string mes = this.serialPort1.ReadLine();
this.BeginInvoke(new AppendMessageDelegate(AppendMessage), new object[] { mes });
}private void AppendMessage(string mes) //受信した文字列の表示
{
this.richTextBox1.AppendText("受信: " + mes + "\r\n");
}private void button2_Click(object sender, EventArgs e) //任意の文字列の送信
{
this.serialPort1.WriteLine(this.textBox2.Text);
this.richTextBox1.AppendText("送信: " + this.textBox2.Text + "\r\n");
}private void Form1_FormClosed(object sender, FormClosedEventArgs e) //終了処理
{
if (this.serialPort1.IsOpen == true)
{
this.serialPort1.Close();
}
this.serialPort1.Dispose();
}}
}制御の中で端末のリブート(電源のON/OFF)が必要で、そこで例外が発生していて、発生箇所は、
string mes = this.serialPort1.ReadLine();
this.serialPort1.Close();
の二か所です。端末の電源が落ちてしまった後、終了処理としてどの様な処理を記述しておくとよいでしょうか?
また、他にも目に余る点がありましたら、ご指摘宜しくお願いいたします。
すべての返信
-
たぶんこれ と同じエラーになることだと思いますが。
USBでCOMポートとして接続している場合、端末側の電源を切ったりコードを抜いたりすると、(ドライバの実装次第でしょうが大抵の場合は)COMポートは消えてしまいます。そうなると存在しないデバイスに対しての操作は出来なくなります。
そのため、ReadLineやCloseで例外となっているんだと思います。
リブートが必要というのは手動で端末を操作して電源ON/OFFするのでしたら、一旦ポートをCloseしてから「電源ON/OFFしてください」とメッセージを出してリブートしてもらい、ポートを監視してデバイスが戻ったら再接続はどうでしょう。
コマンドを送ると自動でリブートする場合は、コマンド送信後に直ぐにCloseすればポートが消える前に閉じられるでしょうが、コマンドが端末に確実に伝わってからリブートが始まるまでの猶予が短いとシビアなタイミングになるかも。
#コマンドを送ると猶予なくリブートしてしまう端末だとしたら、その端末のプロトコルが良くないとしか・・・
上記の手段がとれない場合は、ポートが消えてもせめてアプリが死亡しないようにするには、通信部分をAppDomainで分けて、エラー発生時にはAppDomainごと破棄してやり直すことになりますね。
#AppDomainを破棄すればたぶん掴んでいるリソース開放してくれる
-
AppDomain の使い方は MSDN で調べるといいです。
http://msdn.microsoft.com/ja-jp/library/system.appdomain(VS.80).aspx
上記ページに掲載されているサンプルコードや、中ほどにあるトピックが参考になると思います。
なかむら(http://d.hatena.ne.jp/griefworker) -
DriveDetectorは、以下にてダウンロード可能なコードで、
Jan Dolinayさんという方が作成されているようです。
http://www.codeproject.com/KB/system/DriveDetector.aspx
WM_DEVICECHANGEメッセージとWin32APIを利用したもののようで、
C#標準のクラスではないです。
しいて関連するページとしては、以下です。
http://msdn.microsoft.com/en-us/library/aa363480(VS.85).aspx