0

アプリケーションで不可解な動作が発生しています。

スレッドを作成します。これをワーカーと呼びましょう。これは、通信要求の処理を担当します。スレッドが要求を消費してメッセージを送信している間、クライアントはパイプに書き込みます。

これで、スレッドのメイン ループは次のようになります。

lock(this)
{
  object_id = Transport.BeginSend(xxx, xxx, callback, yyy)
  clientsObjects[object_id] = client_id;
}

ここで、コールバックは client_id にアクセスする必要があります (私が書いたものよりも少し複雑ですが、問題は、コールバックが object_id を受け取ることです。BeginSend がへの呼び出しであると想定してください)。UdpClient.BeginSend

void Callback(IAsyncResult ar)
{
  State st = (State)ar;
  lock(this)
  {
    client_id = clientsObjects[st.object_id]
  }
}

clientsObjects[object_id] = client_id;ロックが存在するのは、コールバックが非常に高速に起動する可能性があるため、実行前に実際に発生する可能性があるためです...

わかりました、今..問題は、それが機能していないことです。まあ、時々機能します...なぜですか?BeginSend を実行しているスレッドとコールバックを実行しているスレッドの ManagedThreadIds をトレースすると、同じ ThreadId を持っていることが時々わかります!!

それは可能ですか?どうすればそれが起こりますか?私が間違っていることについて何か提案はありますか?

コメント: 実際のコードはまったく同じではありません。Transport は UDPClient のラッパーであり、トランスポート層を簡単に変更できます。ロックは実際にはロックではなくスピンロックです ... しかし、概念自体は多かれ少なかれ私が書き留めたものです.

4

1 に答える 1

1

これは、 Stream.BeginRead()関数が実際に同期的に動作することについて説明している古い記事であり、予想どおり非同期ではありません。この記事は2004年のものなので、.NET 1.0/1.1を参照していると思います。この記事では特にUdpClient.BeginSend()については言及していませんが、特にすぐに読み取るデータがある場合、SocketのもののBeginXXX関数が同じ動作をすることがあるのではないかとよく思います。これが可能かどうかを確認するためにWebをチェックする価値があるかもしれません。

BeginSend()関数のstateパラメーターを介してclient_idをコールバック関数に渡すことは可能ですか?

   object_id = Transport.BeginSend(xxx, xxx, Callback, client_id);
于 2009-02-26T14:40:39.517 に答える