none
実装すべき例外処理について教えてください RRS feed

  • 質問

  • .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();

     の二か所です。端末の電源が落ちてしまった後、終了処理としてどの様な処理を記述しておくとよいでしょうか?

    また、他にも目に余る点がありましたら、ご指摘宜しくお願いいたします。

    2010年11月4日 6:10

すべての返信

  • たぶんこれ と同じエラーになることだと思いますが。

    USBでCOMポートとして接続している場合、端末側の電源を切ったりコードを抜いたりすると、(ドライバの実装次第でしょうが大抵の場合は)COMポートは消えてしまいます。そうなると存在しないデバイスに対しての操作は出来なくなります。
    そのため、ReadLineやCloseで例外となっているんだと思います。

    リブートが必要というのは手動で端末を操作して電源ON/OFFするのでしたら、一旦ポートをCloseしてから「電源ON/OFFしてください」とメッセージを出してリブートしてもらい、ポートを監視してデバイスが戻ったら再接続はどうでしょう。
    コマンドを送ると自動でリブートする場合は、コマンド送信後に直ぐにCloseすればポートが消える前に閉じられるでしょうが、コマンドが端末に確実に伝わってからリブートが始まるまでの猶予が短いとシビアなタイミングになるかも。
    #コマンドを送ると猶予なくリブートしてしまう端末だとしたら、その端末のプロトコルが良くないとしか・・・

    上記の手段がとれない場合は、ポートが消えてもせめてアプリが死亡しないようにするには、通信部分をAppDomainで分けて、エラー発生時にはAppDomainごと破棄してやり直すことになりますね。
    #AppDomainを破棄すればたぶん掴んでいるリソース開放してくれる


    • 回答の候補に設定 山本春海 2010年12月1日 2:25
    • 回答の候補の設定解除 山本春海 2010年12月1日 2:27
    2010年11月4日 12:30
  • ご回答有難うございます。

    AppDomainは使用した事が無いのですが、どの様にして使用すればよいのでしょうか?スレッドのように別ブロックに処理を担当させれるものですか?

    お手数ですが、エラー発生時のAppDomainの破棄まで、AppDomainの使用方法をご教授頂けませんでしょうか?

    web上の資料で分かり易い物が無く、少し困ってます。

    2010年11月5日 0:26
  • AppDomain の使い方は MSDN で調べるといいです。

    http://msdn.microsoft.com/ja-jp/library/system.appdomain(VS.80).aspx

    上記ページに掲載されているサンプルコードや、中ほどにあるトピックが参考になると思います。


    なかむら(http://d.hatena.ne.jp/griefworker)
    2010年11月5日 1:34
  • 有難うございます。

    デバイスの抜き差しの検出にDriveDetectorクラスが利用し易いと思うのですが、MSDNライブラリの中に見つけられません。

    海外のMSDNサイトでも良いのですが、仕様を記載しているサイトをどなたかご存知ですか?

     

    2010年11月5日 1:56
  • デバイスの抜き差しの検出にDriveDetectorクラスが利用し易いと思うのですが、MSDNライブラリの中に見つけられません。

    その DriveDetector なるものは .NET 標準ライブラリには存在していません。誰かが作って公開しているものでしょう。

    名前で検索したら十分な XML コメント付きのソースコードがヒットしましたが、それで十分ではないですか?

    2010年11月5日 2:21
  • 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

    2010年11月5日 2:30
  • 本件、現在保留中です。

    2010年11月8日 12:15