[.NET] socketを非同期的に使う

networkへのアクセスを同期してblockする処理から非同期処理に変更する方法。

Asynchronous Client Socket Example( http://msdn.microsoft.com/en-us/library/bew39x2a.aspx )

System.Net.Sockets.Socket classは同期、非同期の両方のメソッドを持っている。
同期式のConnectを非同期式のBeginConnecに変更すると処理は非同期になる。
非同期の場合は、イベント終了時に実行されるCallbackメソッドを指定する。それとともに引数を渡す。少なくともsocketを渡すことが必要。

BeginConnectの中にあるようにcallbackメソッドは別のスレッドで実行される。そのため、一見同じスレッドにあるように見えるオブジェクトが別スレッドに所有されている場合がある。callbackではEndConnectメソッドを呼ぶことが必要。これが非同期なconnectの完了の意味になる。

When your application calls BeginConnect, the system will use a separate thread to execute the specified callback method, and will block on EndConnect until the Socket connects successfully or throws an exception.

client.BeginConnect( remoteEP, new AsyncCallback(ConnectCallback), client);
connectDone.WaitOne();

BeginConnectを発行しWaitOneでsleepして待つ。この間、他スレッドが実行可能になる。ここでconnectDoneは

private static ManualResetEvent connectDone = new ManualResetEvent(false);

と宣言する。callbackでEndConnectが呼ばれるのを待つためのメソッド。このメソッドの実装は UNIXでsignalをselectするのと似ているのではないか。

この方法を使うと、connectしてからcallbackが呼ばれるまでの時間が予想よりもばらつくので、アプリケーションプロトコルがタイムアウトを意識するタイプだと、callbackより先にタイムアウトが発生することがあった。

別スレッドからはオブジェクトの更新もひと手間余計にかかるので、callbackでは最小限の処理だけを行ってEndConnectを呼び出して自分自身は抜けて、メインの処理を続行させるという使い方がこの関数の本来の使い方ではないか。

広告

コメントを残す

コメントを投稿するには、以下のいずれかでログインしてください。

WordPress.com ロゴ

WordPress.com アカウントを使ってコメントしています。 ログアウト / 変更 )

Twitter 画像

Twitter アカウントを使ってコメントしています。 ログアウト / 変更 )

Facebook の写真

Facebook アカウントを使ってコメントしています。 ログアウト / 変更 )

Google+ フォト

Google+ アカウントを使ってコメントしています。 ログアウト / 変更 )

%s と連携中

%d人のブロガーが「いいね」をつけました。