Windows Phone 7 アプリケーションで疑似同期ソケットを使用しています。私のソケット コードはhttp://msdn.microsoft.com/en-us/library/hh202858(v=vs.92).aspxのサンプルに基づいています。
サーバーの送信パターンはやや予測不能です。メッセージの残りの長さを含む固定サイズのヘッダーで始まります。最初にこのヘッダーを読み取り、次に指定されたバイト数をソケットから読み取りました。
サーバーにもメッセージを送信する必要があり、受信用のスレッドと送信用の別のスレッドでソケットを二重化しようとすると、多くの問題が発生したため、コードに次のようなループがあります。
while (KeepConnectionGoing)
{
byte[] Rcvd;
Rcvd = Socket.Receive();//Returns null if no message received in 50 ms
if (Rcvd != null)
{
ParseMessage(Rcvd);
}
if (HasMessageThatNeedsToBeSent())
{
byte[] Message = GetMessageToSend();
Socket.Send(Message);
}
}
これはほとんどの場合問題なく動作しますが、メッセージが null の場合に奇妙なことが起こります。Receive メソッドのタイムアウト (リンクされたサンプルを参照) は ManualResetEvent を使用するため、ソケットの受信要求が実際にキャンセルされることはありません。メソッドが戻ったとしても、そのリクエストはどこかで待機し、ソケットでデータが利用可能になると、ヘッダーをむさぼり食います。イベント ハンドラーは、受信したデータとは何の関係もありません (メソッドが返され、メソッド内の変数が再び使用されることはないため)、データは基本的に消えます。ヘッダースキップを返すと予想される読み取り要求は、ヘッダーの後のバイトを読み取ります。メッセージの長さはわかりません。
ソケットがタイムアウトした場合、未処理のリクエストをすべてキャンセルできるようにしたいと考えています。サンプルのような匿名メソッドを使用しています。これにより、すべてが簡素化され、すべての状態転送コードを自分で記述する必要がなくなります。したがって、イベント ハンドラーをアンフックできません。ただし、メソッドをイベント ハンドラーとして使用していたとしても、非同期操作が完了する前にフックを解除しても、コールバック メソッドが呼び出されると思います。(私はこれをテストしていません、それは私の理解です)
現在、私が見ることができる唯一の解決策は、いくつかの静的なバイト配列をハッキングすることです (つまり、静的な byte[] ヘッダーを持ち、それが null の場合はヘッダーを読み取り、それ以外の場合はメッセージを読み取ります) が、それは本当に洗練されていないソリューションであり、競合状態になりがちです。
より良い方法はありますか?
ありがとう