C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[5]: UDP非同期通信について


(過去ログ 53 を表示中)

[トピック内 6 記事 (1 - 6 表示)]  << 0 >>

■29443 / inTopicNo.1)  UDP非同期通信について
  
□投稿者/ フミ (12回)-(2008/12/09(Tue) 20:24:24)

分類:[C#] 

毎度お世話になります。
フミと申します。

C#にてUDPによる非同期通信を行っています。
通信をやめるためにUdpClientを閉じたところ、
コールバック内で例外が発生してしまい困っています。

ウィンドウズのフォームにボタンが2つあり、
ボタン1を押すとUDPの受信待ち(udpclient.BeginReceive)、
ボタン2を押すとUDPのソケットをクローズ(udpclient.Close)します。

受信はうまくいくのですが、
受信が終わって、ボタン2を押しクローズしようとすると、
非同期受信のコールバック内でエラーが発生します。

エラー内容は

    「破棄されたオブジェクトにアクセスできません。
     オブジェクト名 'System.Net.Sockets.UdpClient' です。」

と表示されます。

コールバックで使うのに先にクローズでUdpClientが破棄されてしまうためだと思われるのですが、
何かプログラムに誤りあるいは対処法ありますでしょうか??


以下、用いたプログラムです。

    //WindowsForm
    public partial class Form1 : Form
    {
        //UDP Client
        UdpStateClass usc;

        //受信データ
        byte[] receiveData;

        //コンストラクタ
        public Form1()
        {
            InitializeComponent();
        }

        //ボタン1クリック イベント
        private void button1_Click(object sender, EventArgs e)
        {
            //UDPStateクラスのインスタンス
            usc = new UdpStateClass();

            //エンドポイントとUDPクライアントを入れます
            usc.endPnt = new IPEndPoint(IPAddress.Any, 44444);
            usc.udpClt = new UdpClient(44444);

            //UDPの非同期受信開始 コールバックはreceiveCallback
            usc.udpClt.BeginReceive(new AsyncCallback(receiveCallback), usc);
        }

        //ボタン2クリック イベント
        private void button2_Click(object sender, EventArgs e)
        {
            //ソケットを閉じる
            usc.udpClt.Close();
        }

        //コールバック
        public void receiveCallback(IAsyncResult ar)
        {
            //IAsysncResultからUDPClientとIPEndPointを受け取る
            UdpClient uc = ((UdpStateClass)(ar.AsyncState)).udpClt;
            IPEndPoint iep = ((UdpStateClass)(ar.AsyncState)).endPnt;

            //受信データを配列に格納
            receiveData = uc.EndReceive(ar, ref iep);
            /* ↑ボタン2を押しcloseすると上の行でエラー発生
             * 「破棄されたオブジェクトにアクセスできません。
             *  オブジェクト名 'System.Net.Sockets.UdpClient' です。」
             */
        }
    }

    //UDPStateクラス
    public class UdpStateClass
    {
        public IPEndPoint endPnt;
        public UdpClient udpClt;
    }

引用返信 編集キー/
■29468 / inTopicNo.2)  Re[1]: UDP非同期通信について
□投稿者/ .SHO (348回)-(2008/12/10(Wed) 10:37:03)
No29443 (フミ さん) に返信

UDPなのでClose処理の最中にコールバックがポストされちゃうのかも知れないですね。
コールバックの処理を try で囲ってしまってはどうでしょう?
引用返信 編集キー/
■29594 / inTopicNo.3)  Re[2]: UDP非同期通信について
□投稿者/ フミ (14回)-(2008/12/11(Thu) 11:49:30)
No29468 (.SHO さん) に返信

返信ありがとうございます!
コールバック内をtry-catchで囲むとエラーはでなくなりました。

しかし、例外があったまま握りつぶしているような気がするので、
もっと根本的な解決をした方が堅牢になるのでしょうね。。。

とりあえず、お教えいただいた通り、このままtry-catchを使ってみます。
よりよい方法も探してみます。
引用返信 編集キー/
■29597 / inTopicNo.4)  Re[3]: UDP非同期通信について
□投稿者/ .SHO (376回)-(2008/12/11(Thu) 12:19:19)
No29594 (フミ さん) に返信

> しかし、例外があったまま握りつぶしているような気がするので、
> もっと根本的な解決をした方が堅牢になるのでしょうね。。。

えっと、そのままではダメです。
私が言いたかったのは Close した後での例外なので
所詮は捨ててしまっても問題ないということです。

従って、確実に対処するには

usc.udpClt.Close();

の前で、フラグを立て try の中でフラグチェックをしてClose処理の
時だけスルーするのが堅牢(?)なシステムです。

引用返信 編集キー/
■29890 / inTopicNo.5)  Re[4]: UDP非同期通信について
□投稿者/ フミ (15回)-(2008/12/16(Tue) 12:14:19)
2008/12/16(Tue) 12:16:25 編集(投稿者)
No29597 (.SHO さん) に返信

返信ありがとうございます!

        Flag = true;
        usc.udpClt.Close();

で

        //コールバック
        public void receiveCallback(IAsyncResult ar)
        {
             try{
                if(!Flag)
        {
                   //処理
                }
             }
             catch
             {
                 //何もしない
             }
        }

でしょうか?
ひとまずこれでやってみます。

引用返信 編集キー/
■29891 / inTopicNo.6)  Re[5]: UDP非同期通信について
□投稿者/ .SHO (418回)-(2008/12/16(Tue) 12:21:49)
No29890 (フミ さん) に返信

> でしょうか?

ごめんなさい。表現が正確じゃなかったです。
フラグチェックするのは、try の中じゃなくて catch の中です。

try の中の処理そのものを フラグで囲ってしまうのなら
try はいらないですね。

その方法でもいいかも?
どっちでもいいです。
引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -