DOBON.NET DOBON.NETプログラミング掲示板過去ログ

コールバック関数に値を渡したい

環境/言語:[OS:XP(SP2) Framework1.1]
分類:[.NET]

こんにちは

Socketで非同期のTCP通信を行っています。

Dim client as Socket
(中略)

client.BeginConnect(remoteEP, New AsyncCallback(AddressOf _ ConnectCallback), client)

クラスライブラリには"コールバック メソッドの宣言のパラメータは、AsyncCallback デリゲート
の宣言と同じでなければならなりません"とあります。
しかし複数の通信を同時に行うため、接続、受信 のCallback関数にデリゲートの宣言以外の値を
引数として渡したいのですがそのようなことは可能でしょうか?

よろしくお願い致します。
> しかし複数の通信を同時に行うため、接続、受信 のCallback関数にデリゲートの宣言以外の値を
> 引数として渡したいのですがそのようなことは可能でしょうか?

Socket.BeginConnect() のヘルプの「解説」欄に

--ここから--
state パラメータを使用して、 Socket を BeginConnect に渡さなければなりません。他の情報がコールバックに必要な場合は、小さなクラスを作成して Socket などの必要な情報を保持します。このクラスのインスタンスは、 state パラメータを使用して BeginConnect メソッドに渡します。
--ここまで--

と書かれていますが、それではダメですか?

機械翻訳っぽい低品質の解説ですが、よく読めば道が開けるかと。
ご連絡ありがとうございます。

> Socket.BeginConnect() のヘルプの「解説」欄に
>
> --ここから--
> state パラメータを使用して、 Socket を BeginConnect に渡さなければなりません。他の情報がコールバックに必要な場合は、小さなクラスを作成して Socket などの必要な情報を保持します。このクラスのインスタンスは、 state パラメータを使用して BeginConnect メソッドに渡します。
> --ここまで--
>
> と書かれていますが、それではダメですか?
>
> 機械翻訳っぽい低品質の解説ですが、よく読めば道が開けるかと。

その解説は知っているのですが、どうすればいいのか分からないといった状況なのです。
> その解説は知っているのですが、どうすればいいのか分からないといった状況なのです。

解説に書かれているとおり、「小さなクラス」を作成し、そこに必要な情報をすべて詰め込んで Socket.BeginConnect() すればよいのです。

要するに

public class ParamClass
{
public string Hoge;
}

ParamClass param = new ParamClass();
hoge.Hoge = "ほげ";

socket.BeginConnect (remoteIP, new AyncCallback (MyCallback), hoge);

とすると、hoge が、MyCallback が呼び出された時の引数 IAsyncResult ar の AsyncState メンバとして引き渡されるということです。

なので、

ParamClass param = (ParamClass) ar.AsyncState;

のようにして、BeginConnect() の引数に与えた hoge を、MyCallback 内で参照することが出来ます。
不勉強ですみません。

引数にソケットではなく、クラスを渡すようにしてみました。
すると「指定されたキャストは有効でありません」と、エラーになってしまいます。
コールバック関数にソケットがわたっていないようなのですが・・・
クラスの設定に間違いがあるのでしょうか?

Public Class TCPTEST

 Dim connectDone = New ManualResetEvent(False)

Sub TestTCP_Open()
 Dim IP as String = "xxx.xxx.xxx.xxx"
 Dim Port as Integer = 33340
 Dim remoteEP = New IPEndPoint(IPAddress.Parse(IP), port)
 Dim myClient as Socket = Nothing

 myClient = my_connect(remoteEP) '接続する

End Sub

'接続用関数
Public Function my_connect(ByVal remoteEPX As IPEndPoint) As Socket

 Dim client As Socket = Nothing

 client = New Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)

 Dim hoge As New ParamClass
 hoge.Hoge = "テスト"
 hoge.Client = client

 Try
   connectDone.Reset()

   'client.BeginConnect(remoteEPX, New AsyncCallback(AddressOf ConnectCallback), Client)
   '※修正渡すのはclientではなくてクラスに変更
   client.BeginConnect(remoteEPX, New AsyncCallback(AddressOf ConnectCallback), hoge)

   If connectDone.WaitOne(3000, False) Then '接続を待つ。
     '正常に接続
   Else 'タイムアウト
    client.Close()
   End If

 Catch ex As Exception
   MsgBox(e.ToString)
 End Try

 Return client

End Function

'コールバック関数
Public Sub ConnectCallback(ByVal ar As IAsyncResult)

 Dim param As ParamClass = CType(ar.AsyncState, ParamClass)
 Dim s As String = param.Hoge

 Try
  Dim client As Socket = CType(ar.AsyncState, Socket)

  client.EndConnect(ar)

 Catch e As Exception
  MsgBox(e.ToString())

 End Try

 connectDone.Set()

End Sub

End Class

'パラメータ用のクラスの宣言
Public Class ParamClass

 Public Hoge As String
 Public Client As Socket

End Class
>すると「指定されたキャストは有効でありません」と、エラーになってしまいます。

「エラー」つっても色々あるわけですが、どんなエラーですか?
コンパイルエラーですか?

おそらくコンパイルエラーだとして、どの行で発生してるかくあいは書いてくださいな。

ぱっと見で変なとこは

>   Dim client As Socket = CType(ar.AsyncState, Socket)
>   client.EndConnect(ar)

です。

>  Dim param As ParamClass = CType(ar.AsyncState, ParamClass)
>  Dim s As String = param.Hoge

としてる位なんで、

Dim clietn As Socket = param.Client

なのでは。
> 「エラー」つっても色々あるわけですが、どんなエラーですか?
> コンパイルエラーですか?

すみません。大事なことを書き忘れていました。
実行時エラーです。

Dim client As Socket = CType(ar.AsyncState, Socket)
の行を実行するとエラーになります。


> ぱっと見で変なとこは
>
>>  Dim client As Socket = CType(ar.AsyncState, Socket)
>>  client.EndConnect(ar)

これを
 Dim CC As Socket = param.Client

Dim client As Socket = CType(CC, Socket)

にしたらうまく接続できました。
その他の値もとれています。
本当にありがとうございます。
解決済み!

DOBON.NET | プログラミング道 | プログラミング掲示板